java的泛型所采用的是一种类型消除(type erasure)的机制来实现的。编译器使用泛型类型信息来编译代码,但是随后会消除它。所以,泛型信息只是在编译器可用,而在运行时是不可用的。这种机制的好处在于可以使泛型代码向后兼容使用原始类型的遗留代码。
在编译时,一旦编译器确认泛型类型是安全使用的,就会将它转换为原始类型。举个例子:
ArrayList<String> list= new ArrayList<String>();
list.add("xxxxxxx");
String state = list.get(0);
编译器会检查上面代码里泛型是否被正确使用,如果上面的add方法加的是非String类型的话,会报编译错。在确认编译正确后,会将它翻译成为下述代码:
ArrayList list= new ArrayList();
list.add("xxxxxxx");
String state = (String)(list.get(0));
当编译泛型类、接口和方法时,编译器用Object类型代替泛型类型。再举个例子:
public static<E> void print(E[] list){
for(int i=0;i<list.length;i++)
System.out.println(list[i]+" ");
System.out.println();
}
上述代码在编译通过后,会翻译成为如下:
public static<Object> void print(Object[] list){
for(int i=0;i<list.length;i++)
System.out.println(list[i]+" ");
System.out.println();
}
如果一个泛型类型是不受限的,那么编译器会用一个受限类型来替代它,继续举个例子:
public static <E extends GeomentObject>boolean equalArea(E object1,E object2){
return object1.getArea()==object2.getArea();
}
上述代码在编译通过后,会被翻译成如下:
public static <E extends GeomentObject>boolean equalArea(GeomentObject object1,GeomentObject object2){
return object1.getArea()==object2.getArea();
}
非常需要注意的是,不管实际的具体类型是什么,泛型类是被它的所有实例所共享的。假如按照如下方式创建list1和list2:
ArrayList <String> list1 = new ArrayList <String>();
ArrayList <Integer> list2 = new ArrayList <Integer>();
尽管在编译期ArrayList <String> list和ArrayList <Integer> list是两种类型,但是在运行时只有一个ArrayList类会被加载到JVM,list1和list2都是ArrayList的实例,因此,下面两条语句的执行结果都为true:
System.out.println(list1 instanceof ArrayList);
System.out.println(list2 instanceof ArrayList);