我读过Java的类型擦除在甲骨文的网站上。
什么时候发生类型擦除?在编译时还是运行时?什么时候加载类?类何时实例化?
很多网站(包括上面提到的官方教程)都说类型擦除发生在编译时。如果在编译时完全删除了类型信息,当调用使用泛型的方法时没有类型信息或类型信息错误时,JDK如何检查类型兼容性?
假设类A
有一个方法empty(Box<? extends Number> b)
。我们编译A.java
并得到类文件A.class
。
public class A {
public static void empty(Box<? extends Number> b) {}
}
public class Box<T> {}
现在我们创建另一个类B
,它使用一个非参数化参数(原始类型)调用方法empty
: empty(new Box())
。如果我们在类路径中编译B.java
和A.class
, javac足够聪明,会发出警告。所以A.class
有一些类型信息存储在它里面。
public class B {
public static void invoke() {
// java: unchecked method invocation:
// method empty in class A is applied to given types
// required: Box<? extends java.lang.Number>
// found: Box
// java: unchecked conversion
// required: Box<? extends java.lang.Number>
// found: Box
A.empty(new Box());
}
}
我的猜测是,类型擦除发生在类加载时,但这只是一个猜测。那么什么时候发生呢?