【发布时间】:2023-03-29 10:16:01
【问题描述】:
我了解到 Java 的类型擦除 on Oracle's website。
什么时候发生类型擦除?在编译时还是运行时?什么时候加载类?什么时候实例化类?
很多网站(包括上面提到的官方教程)都说类型擦除发生在编译时。如果在编译时完全去掉了类型信息,那么在没有类型信息或类型信息错误的情况下调用使用泛型的方法时,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());
}
}
我的猜测是加载类时会发生类型擦除,但这只是猜测。那么什么时候发生呢?
【问题讨论】:
-
这个问题的更“通用”版本:stackoverflow.com/questions/313584/…
-
@afryingpan:我的回答中提到的文章详细解释了类型擦除发生的方式和时间。它还解释了何时保留类型信息。换句话说:物化泛型在 Java 中是可用的,这与普遍的看法相反。见:rgomes.info/using-typetokens-to-retrieve-generic-parameters
标签: java generics type-erasure