Java泛型 - 类型擦除 - 何时和发生什么 [英] Java generics - type erasure - when and what happens

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

问题描述

我在Oracle网站上阅读了Java的类型删除

何时发生类型擦除?在编译时/运行时?当类加载/运行时?当类被实例化时?



很多站点(包括上面提到的Sun教程)都说类型擦除发生在编译时。如果类型信息在编译时被完全删除,那么当调用没有类型信息或错误类型信息的使用泛型的方法时,JDK检查类型兼容性如何。假设类A有一个方法, empty(Box<?extends Number> b) 。我们编译A.java并获取类文件A.class。

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



我的猜测是类加载时发生类型擦除,但它只是一个猜测。那么它何时发生?

解决方案

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

  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 <
$ b

...但是列表< T> 对于列表对象 - 该信息不存在。编辑:只是为了澄清,编译器确实保留了有关变量的信息是一个 List< String> - 但你仍然无法找到列表对象本身的 T = String 。 / p>

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

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

A lot of sites (including the Sun 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.

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.

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.

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

解决方案

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

is compiled into

List list = new ArrayList();
list.add("Hi");
String x = (String) list.get(0);

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

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

EDIT: 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天全站免登陆