Java 泛型 - 擦除机制

Java Generics - Erasures Mechanism

说..,Java 编译器擦除所有类型信息,并用它们的上限(如果提到)或 Object..

替换所有出现的类型信息

我的问题是:这里没有插入演员表。当一些其他class针对此类型无信息class编译时,稍后会发生转换,其中,根据其他class补充的类型参数,通用class 被重新编译(第二次)并且所有转换都已到位并且 class 已准备好 运行 时间..,对吧?

不,class 没有重新编译。转换发生在具体类型和通用类型之间的边界上。

如果您想弄明白,您可以考虑使用泛型 class 作为原始类型(即没有泛型)。例如 ArrayList:

List l = new ArrayList(); // An `ArrayList<String>` before generics.

l.add("Hello");
String s = (String) l.get(0);

在已知具体类型的地方插入强制转换(在本例中为String)。它们 不是 插入 ArrayList class 中,实际上没有必要。

Casting occurs later when some other class is compiled against this type info-free class,

不,转换是在 class 本身的编译阶段执行的。
编译出来的class应该不会根据依赖的classes改变。

看看这个方法:

public class TestCast {

    public void doSomething(){
       List<Integer> values = new ArrayList<>();
       values.add(1);
       Integer value = values.get(0);
    }
}

这里是TestCast编译的class的反汇编方法(用javap工具完成):

public void doSomething();
   Code:
      0: new           #15                 // class java/util/ArrayList
      3: dup
      4: invokespecial #17                 // Method java/util/ArrayList."<init>":()V
      7: astore_1
      8: aload_1
      9: iconst_1
     10: invokestatic  #18                 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
     13: invokeinterface #24,  2           // InterfaceMethod java/util/List.add:(Ljava/lang/Object;)Z
     18: pop
     19: aload_1
     20: iconst_0
     21: invokeinterface #30,  2           // InterfaceMethod java/util/List.get:(I)Ljava/lang/Object;
     26: checkcast     #19                 // class java/lang/Integer
     29: astore_2
     30: return

强制转换确实是由编译器添加的:

 26: checkcast     #19                 // class java/lang/Integer

目前没有提到的其他答案是桥接方法。

例如

public class GenericTest implements Comparable<GenericTest>{

    @Override
    public int compareTo(GenericTest o) {
        return 0;
    }
}

编译器实际上会创建两个方法。 int compareTo(Object); 投射和转发以及预期的 int compareTo(GenericTest)