泛型是使用一種稱爲類型消除的方法實現的。編譯器使用泛型類型信息來編譯代碼,但是隨後會消除它。因此,泛型信息在運行時是不可用的。這種方法可以使泛型向後兼容使用原始類型的遺留代碼。
泛型存在於編譯時。一旦編譯確認泛型類型是安全的,就會將他轉換爲原始類型。例如,編譯器會檢查例子中的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){
......
}