繁体   English   中英

Java类型擦除 - 为什么我在查看字节码时能看到类型?

[英]Java type erasure - why can I see the type when I look at the bytecode?

我试图理解为什么不允许在类中编写这两个方法

 public bool plus(List<String>) {return true;}
 public bool plus(List<Integer>) {return true;}

我试图弄清楚它与类型擦除有什么关系,但是当我反编译以下代码时

public class Test<T> {

   boolean plus2(List<T> ss) {return false;}
   boolean plus(List<String> ss) {return false;}
   boolean plus(Set<Integer> ss) {return false;}
}

当我用Java反编译器(jd)反编译它时,我得到了同样的结果

即使我打印字节代码,我也可以清楚地看到类型。
(看看那些声明'但是确保在字节码中删除类型'的答案 ')

    Compiled from "Test.java"
    public class com.example.Test<T> {
    public com.example.Test();
            Code:
            0: aload_0
            1: invokespecial #1                  // Method java/lang/Object."<init>":()V
            4: return

            boolean plus2(java.util.List<T>);
            Code:
            0: iconst_0
            1: ireturn

            boolean plus(java.util.List<java.lang.String>);
            Code:
            0: iconst_0
            1: ireturn

            boolean plus(java.util.Set<java.lang.Integer>);
            Code:
            0: iconst_0
            1: ireturn
            }

您的编译器需要能够根据字节代码中的信息检查泛型类型信息。

Java 5.0+以字节代码记录通用信息,但它不会将其记录在对象实例中。

例如,无法获得此列表的泛型类型

 // list.getClass() is just ArrayList which doesn't record the generic type.
List list = new ArrayList<String>();

不过这样做

// list.getClass() is not ArrayList
// list is an instance of a class which extends ArrayList<String>
List list = new ArrayList<String>() { };

ParameterizedType t = (ParameterizedType) list.getClass().getGenericSuperclass();
assert t.getRawType() == ArrayList.class;
assert t.getActualTypeArguments()[0] == String.class;

这是因为ArrayList的子类的字节代码记录了它的父类中使用的泛型。

注意:这也适用于字段,构造函数/方法参数作为返回类型,实际类型记录在字节代码中。

但是,这些都不意味着实例的泛型类型可用(尽管如果以字节代码记录,父类/接口的泛型类型可用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM