泛型

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 域。 因此, 禁止使用帶有類型變量的靜態域和方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章