Java 泛型类型删除 : when and what happens?

标签 java generics type-erasure

我读到了 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.javaA.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());
    }
}

我的猜测是类被加载时会发生类型删除,但这只是一个猜测。那么它什么时候发生?

最佳答案

类型删除适用于泛型的使用。类文件中肯定有元数据来说明方法/类型泛型,以及约束是什么等等。但是当使用泛型时,它们会被转换分为编译时检查和执行时转换。所以这段代码:

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>接口(interface)本身仍然标榜自己是通用的。

编辑:澄清一下,编译器确实保留了有关变量List<String> 的信息。 - 但你仍然找不到 T=String对于列表对象本身。

关于Java 泛型类型删除 : when and what happens?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37302321/

相关文章:

java - 集成测试将整个对象发布到 Spring MVC Controller

java - 将char[]转换为BigDecimal[],一般概念

java - Java 泛型的 'E' 、 'T' 和 '?' 有什么区别?

java - Generic 中的类型转换错误

Java泛型方法通配符不匹配问题

java - 实现队列,使其通用时出现错误

java - 当 TextView 在 fragment 内的 onLocationChanged 内更改时应用程序崩溃

Scala:具有多个来源和异构类型的交叉(笛卡尔)积

swift - 使用 `Self` 作为参数的方法键入删除

ios - 无法将类型 'AnyDataSource<NSManagedObjectSubclass>' 的值分配给类型 'AnyDataSource<NSManagedObject>' 的值