泛型是使用一种称为类型消除的方法实现的。编译器使用泛型类型信息来编译代码,但是随后会消除它。因此,泛型信息在运行时是不可用的。这种方法可以使泛型向后兼容使用原始类型的遗留代码。
泛型存在于编译时。一旦编译确认泛型类型是安全的,就会将他转换为原始类型。例如,编译器会检查例子中的a代码里的泛型是否使用正确,然后就将他翻译成b中的使用的等价代码。
a: ArrayList list=new ArrayList();
list.add("ok");
String state=list.get(0);
b:ArrayList list=new ArrayLiat();
list.add("ok");
String state=(String)(list.get(0))
当编译泛型类,接口和方法时,编译器用Object类型代替泛型类型,例如没编译器会将a中的方法转换成b中的方法:
a:
public staticvoid print(E[] list){
for(int i=0;i
System.out.print(list[i]+"");
System.out.print("\n");
}
b:
public static void print(Object[] list){
for(int i=0;i
System.out.print(list[i]+"");
System.out.print("\n");
}
如果一个泛型类型是受限的,那么编译器就会用一个受限类型来替换他。例如下面的例子:
a:
public static boolean equalArea(E object1,E object2){
return object1.getArea()==object2.getArea();
}
b:
public static boolean equalArea(GeometricObject object1,GeometricObject object2){
return object1.getArea()==object2.getArea();
}
对泛型的限制:
1.不能使用new E():不能使用泛型类型参数创建实例。例如下面的语句是错误的:
E object=new E();
出错的原因是运行时执行的new E(),但是运行时泛型类型是不可用的。
2.不能使用new E[]:不能使用泛型类型参数创建数组,例如下面的语句是错误的:
E[] elements=new E[capacity];
可以通过创建一个Objectl类型的数组,然后将他的类型转换为E[]来规避这个限制,例如:
E elements=(E[])new Object[capacity];
但是,类型转换会导致一个免检的编译警告。该警告会出现是因为编译器无法确保在运行时类型转换能成功。例如,如果E是String,而new Object[]是Integer对象的数组,那么(String [])(new Object[])会导致ClassCastException异常。这种类型的编译警告是对Java泛型的限制,也是无法避免的。
不能使用泛型类型创建泛型数组,例如,下面的代码是错误的:
ArrayList[]list=new ArrayList[10];
可以使用下面的代码来规避这种限制:
ArrayList[] list=(ArrayList[])new ArrayList[10];
3.在静态环境下不允许类的参数是泛型类型
由于泛型类的所有实例都有相同的运行时类,所以泛型类的静态变量和方法是被她的所有实例所共享的。因此,在静态方法中,数据域或者初始化语句中,为了类引用泛型类型参数是非法的
4.异常类不能使泛型的
泛型类不能扩展java.lang.Throwable,因此,下面的类声明是非法的:
public class MyException extends Expection{
}
为什么?JVM必须检查这个从try子句中抛出的异常以确定它是否与catch子句中指定的类型匹配。但这是不可能的,因为在运行时类型信息室不出现的。
try{
......
}cache(Myexpection ex){
......
}