前段时间在上国外某教授的algorithm课程,提到在java中不能创建泛型数组,课后也有这个思考题,自己百思不得其解,于是翻开了《think in java》这本书,在书的第15章,写到。这是由于擦除机制。(尽管通读了第15章,小白作者还是有很多地方不明白,如果读者能明白,望不吝赐教)
public class ErasedTypeEquicalence {
public static void main (Sring args[]){
Class c1=new Arraylist().getClass();
Class c2=new Arraylist().getClass();
System.out.println(c1==c2);
}
/*ourput:
*true
*/
}
在下面,书上又介绍了另一端比较长的例子。
//: generics/LostInformation.java
import java.util.*;
class Frob {}
class Fnorkle {}
class Quark {}
class Particle {}
public class LostInformation {
public static void main(String[] args) {
List list = new ArrayList();
Map map = new HashMap();
Quark quark = new Quark();
Particle p = new Particle();
System.out.println(Arrays.toString(
list.getClass().getTypeParameters()));
System.out.println(Arrays.toString(
map.getClass().getTypeParameters()));
System.out.println(Arrays.toString(
quark.getClass().getTypeParameters()));
System.out.println(Arrays.toString(
p.getClass().getTypeParameters()));
}
} /* Output:
[E]
[K, V]
[Q]
[POSITION, MOMENTUM]
*///:~
Class.getTypeParemeters() 将 "返回一个TypeVarivable的对象数组表示有泛型声明所声明的类型参数",好像暗示我们可能发现参数类型的信息,但是从输出我们可以看到,能够发现的只是用作参数占位符的标识符,这,并没有什么卵用。
书上提到了:这是一个残酷的现实:在泛型代码内部,无法获得任何有关泛型参数类型的信息。
泛型是通过擦除实现的,这意味着当你使用泛型时,任何具体的类型信息都被擦除了,你唯一所知道的就是你在使用一个对象。之前说的arraylist<String>和arraylist<Integer>在运行时会被擦除成“原生”的类型,即list。
书上提到了 泛型不是java语言出现就有的组成成分,所以为了减少擦除的混淆,我们要意识到,擦除是java语言实现泛型的一种折中,这种折中会让我们痛苦。。由于擦除的存在,泛型在java中的使用不像它原来设想的那么有用,尽管还是存在用处。
擦除的核心动机是它使得泛化的客户端可以用非泛化的类库,反之亦然,这经常被称为“迁移兼容性”。
擦除的代价是显著的,泛型不能用于显式地引用运行时类型的操作之中,例如转型、instanceof操作和new表达式。因为所有关于参数的类型信息都已经丢失了。
因此像 public class Eraesd<T>{
....
T [] arrary =new T[size] ;//这样的代码会出现error (won't compile)
...
}