我读到了有关 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
with A.class
在类路径中,javac 足够聪明,可以发出警告。所以A.class
has其中存储了一些类型信息。
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());
}
}
我的猜测是,加载类时会发生类型擦除,但这只是猜测。那么什么时候发生呢?
类型擦除适用于use的仿制药。类文件中肯定有元数据来说明是否有方法/类型is泛型,以及约束是什么等。但是当泛型是used,它们被转换为编译时检查和执行时强制转换。所以这段代码:
List<String> list = new ArrayList<String>();
list.add("Hi");
String x = list.get(0);
被编译成
List list = new ArrayList();
list.add("Hi");
String x = (String) list.get(0);
在执行时没有办法发现这一点T=String
对于列表对象 - 该信息消失了。
...但是List<T>
接口本身仍然标榜自己是通用的。
编辑:只是为了澄清,编译器确实保留了有关variable成为一个List<String>
- 但你还是无法发现T=String
对于列表对象本身。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)