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)
说..,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)