Java泛型类型擦除:何时以及发生了什么? [英] Java generics type erasure: when and what happens?

查看:378
本文介绍了Java泛型类型擦除:何时以及发生了什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Oracle的网站上阅读了有关Java的类型擦除的内容

I read about Java's type erasure on Oracle's website.

何时发生类型擦除?在编译时或运行时?什么时候上课?当实例化类时?

When does type erasure occur? At compile time or runtime? When the class is loaded? When the class is instantiated?

很多站点(包括上面提到的官方教程)都说在编译时会发生类型擦除。如果在编译时完全删除了类型信息,那么当调用使用泛型的方法而没有类型信息或错误的类型信息时,JDK如何检查类型兼容性?

A lot of sites (including the official tutorial mentioned above) say type erasure occurs at compile time. If the type information is completely removed at compile time, how does the JDK check type compatibility when a method using generics is invoked with no type information or wrong type information?

考虑以下示例:Say class A 有一个方法,为空(Box<?  extends  Number>  b)。我们编译 A.java 并获取类文件 A.class

Consider the following example: Say class A has a method, empty(Box<? extends Number> b). We compile A.java and get the class file A.class.

public class A {
    public static void empty(Box<? extends Number> b) {}
}





public class Box<T> {}

现在我们创建另一个类 B 它使用非参数化参数(原始类型)调用方法 empty empty(new Box())。如果我们在类路径中使用 A.class 编译 B.java ,javac足够聪明地发出警告。所以 A.class 存储了一些类型信息。

Now we create another class B which invokes the method empty with a non-parameterized argument (raw type): empty(new Box()). If we compile B.java with A.class in the classpath, javac is smart enough to raise a warning. So A.class has some type information stored in it.

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());
    }
}

我的猜测是类的擦除发生在课堂上加载了,但这只是猜测。那么什么时候发生?

My guess would be that type erasure occurs when the class is loaded, but it is just a guess. So when does it happen?

推荐答案

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

Type erasure applies to the use of generics. There's definitely metadata in the class file to say whether or not a method/type is generic, and what the constraints are etc. But when generics are used, they're converted into compile-time checks and execution-time casts. So this code:

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 用于列表对象 - 该信息已消失。

At execution time there's no way of finding out that T=String for the list object - that information is gone.

...但列表< T> 接口本身仍然宣称它是通用的。

... but the List<T> interface itself still advertises itself as being generic.

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

Just to clarify, the compiler does retain the information about the variable being a List<String> - but you still can't find out that T=String for the list object itself.

这篇关于Java泛型类型擦除:何时以及发生了什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆