由於泛型類型在運行時被消除,因此,對於如何使用泛型類型是有一些限制的。
限制1:不能使用new E()
不能使用泛型類型參數創建實例。例如,下面的語句是錯誤的:
E object = new E();
出錯的原因是運行時執行的是new E(),但是運行時泛型類型E是不可用的。
限制2:不能使用new E[]
不能使用泛型類型參數創建數組。例如,下面的語句是錯誤的。
E[] elements = new E[capacity];
可以通過創建一個Object類型的數組,然后將它的類型轉換為E[]來規避這個限制,如下所示:
E[] elements = (E[]) new Object[capacity];
但是,類型轉換到(E())會導致一個免檢的便已警告。該警告會出現是因為編譯器無法確保在運行時類型轉換能成功。例如,如果E是String,而new Object[]是Integer對象的數組,那么(String[])(new Object[])將會導致ClassCastException異常。這種類型的編譯警告是對Java泛型的限制,也是無法避免的。
不能使用泛型類創建泛型數組。例如,下面的代碼是錯誤的:
ArrayList<String> list = new ArrayList<String>[10];
可以使用下面的代碼來規避這個限制:
ArrayList<String> list = (ArrayList<String>[]) new ArrayList[10];
你將會得到一個編譯警告。
限制3:在靜態環境下不允許類的參數是泛型類型
由於泛型類的所有實例都有相同的運行時類,所以泛型類的靜態變量和方法是被它的所有實例所共享的。因此,在靜態方法、數據域或者初始化語句中,為了類而引用泛型類型參數是非法的。例如,下面的代碼是非法的:
public class Test<E> {
public static void m(E o1) { // Illegal
}
public static E o1; // Illegal
static {
E o2; // Illegal
}
}
限制4:異常類不能是泛型的
泛型類不能擴展java.lang.Throwable,因此,下面的類聲明是非法的:
為什么?如果允許這么做,就應為MyException<T>添加一個catch子句,如下所示:
public class MyException<T> extends Exception {
}
JVM必須檢查這個從try子句中拋出的異常以確定它是否與catch子句中指定的類型匹配。但這是不可能的,因為在運行時類型信息是不出現的。
try {
...
}
catch (MyException<T> ex) {
...
}