1. 類型擦除
虛擬機中沒有泛型,只有普通的類和方法。定義一個泛型類型,會進行類型擦除,如:
public class Pair<T>
{
private T first;
private T second;
public Pair() { first = null; second = null; }
public Pair(T first, T second) { this.first = first; this.second = second; }
public T getFirst() { return first; }
public T getSecond() { return second; }
public void setFirst(T newValue) { first = newValue; }
public void setSecond(T newValue) { second = newValue; }
}
會被擦除爲:
public class Pair<T>
{
private Object first;
private Object second;
public Pair() { first = null; second = null; }
public Pair(Object first, Object second) { this.first = first; this.second = second; }
public Object getFirst() { return first; }
public Object getSecond() { return second; }
public void setFirst(Object newValue) { first = newValue; }
public void setSecond(Object newValue) { second = newValue; }
}
2. 類型翻譯
當程序調用泛型方法時,編譯器插入強制類型轉換。如
Pair<Employee> buddies = ...;
Employee buddy = buddies.getFirst();
擦除 getFirst 的返回類型後將返回 Object 類型。編譯器自動插入 Employee 的強制類型轉換。也就是說,編譯器把這個方法調用翻譯爲兩條虛擬機指令:
- 對原始方法 Pair.getFirst 的調用。
- 將返回的 Object 類型強制轉換爲 Employee 類型。
3. 泛型的限制
-
不能用基本類型實例化類型參數。因此,沒有 Pair< double>, 只 有 Pair< Double >。 其原因是類型擦除。擦除之後,Pair 類含有 Object 類型的域, 而 Object 不能存儲 double 值。
-
運行時類型查詢只適用於原始類型。
if (a instanceof Pair<String>) // Error
實際上僅僅測試 a 是否是任意類型的一個 Pair。同樣的道理, getClass 方法總是返回原始類型。Pair<String> stringPair = . . Pai「< Employee〉employeePair = . . if (stringPair.getClassO == employeePair.getClassO) // they are equal
-
不能實例化參數化類型的數組。數組會記住它的元素類型, 如果試圖存儲其他類型的元素, 就會拋出一個 ArrayStoreException 異常,對於泛型類型,擦除會使這種機制無效。
Pair<String>[] table = new Pair<String>[10]; // Error Object[] objarray = table; objarray[0] = new Pair<Employee>();//能夠通過數組存儲檢查
需要說明的是, 只是不允許創建這些數組, 而聲明類型爲 Pair< String>[] 的變量仍是合法的。不過不能用 new Pair< String>[10] 初始化這個變量。
-
泛型類的靜態上下文中類型變量無效。不能在靜態域或方法中引用類型變量。
public class Singleton<T> { private static T singlelnstance; // Error public static T getSinglelnstanceO // Error { if (singleinstance == null) construct new instance of T return singlelnstance; } }
如果這個程序能夠運行, 就可以聲明一個 Singleton< Random> 共享隨機數生成器, 聲明一個 Singleton< JFileCh00Ser> 共享文件選擇器對話框。 但是, 這個程序無法工作。類型擦除之後, 只剩下 Singleton 類, 它只包含一個 singlelnstance 域。 因此, 禁止使用帶有類型變量的靜態域和方法。