类型擦除(Type Erasure)
当我们实例化一个泛型的时候,编译器使用一种叫做类型擦除(type erasure)的技术。在类型擦除的过程中,编译器会去除掉 类与接口中所有和类型参数有关的信息。类型擦除使得用泛型的java应用程序能够和该泛型创建之前就存在的java库和应用程序相兼容。
例如Box<String>在编译的时候产生一个叫做原型(raw type)的类型Box,而所谓原型就是没有任何参数的泛型类名或者接口名。这也就是说,在运行的时候我们不知道一个泛型类究竟是什么类型的对象。如下的代码在编译的时候就会报错:
public class MyClass<E> {
public static void myMethod(Object item) {
if (item instanceof E) { //Compiler error
...
}
E item2 = new E(); //Compiler error
E[] iArray = new E[10]; //Compiler error
E obj = (E)new Object(); //Unchecked cast warning
}
}
上面黑体代码之所以在编译的时候会报错是因为编译器去除了所有和参数(由类型参数E代表)相关的信息。
有了类型擦除技术之后,就可以让新的代码和遗留的代码共存。但是无论如何,使用原型是一种不好的编程习惯,应该避免在程序中使用。当把遗留代码和泛型代码混合在一起的时候,我们可能会碰到类似于下面的告警:
Note: WarningDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
例如,我们用一个旧的API,但参数却用的是一个原型参数,如下的代码所示:
public class WarningDemo {
public static void main(String[] args){
Box<Integer> bi;
bi = createBox();
}
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
static Box createBox(){
return new Box();
}
}
我们用 -Xlint:unchecked 重新编译就会显示出如下附加的信息:
WarningDemo.java:4: warning: [unchecked] unchecked conversion
found : Box
required: Box<java.lang.Integer>
bi = createBox();
^
1 warning
文章评论(0条评论)
登录后参与讨论