首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

輕鬆掌握 Java 泛型(二):型別擦除帶來的五大限制深度解析

     編輯:Java 相關知識

J2SE 1.5(Tiger)將納入泛型類型(JSR-14 原型已可下載)。第一部分介紹基礎與重要性,本文詳細說明 Tiger/JSR-14 禁止的五大使用限制,並揭示其根源:型別擦除實現策略的必然結果。

五大限制

  1. 靜態成員中不可引用封閉類型參數
  2. 不可用基本型別實例化泛型參數
  3. 不可在型別轉換或 instanceof 中使用「外露」類型參數
  4. 不可在 new 操作中使用「外露」類型參數
  5. 不可在 implements/extends 子句中使用「外露」類型參數

JVM 不支援泛型,編譯器「耍花招」:用泛型資訊檢查代碼,隨即擦除所有泛型生成僅含普通型別的類別檔。List<T> 擦除為 List,「外露」參數(單獨出現的參數)擦除為其界限(T → Object)。此技術兼容性極強(新舊代碼無縫協作),但引入型別系統缺陷,限制泛型使用安全性。

前三大限制詳析

1. 靜態成員中的封閉類型參數

編譯器完全禁止靜態方法/靜態內部類引用封閉類型參數。靜態欄位更隱蔽:JSR-14 1.0/1.2 允許引用但共享單一靜態欄位,導致運行時 ClassCastException 甚至無轉型代碼:

class C<T> { static T member; C(T t){ member=t; } T getMember(){return member;} }
C<String> c = new C<String>("test");
new C<Integer>(new Integer(1)); // 覆寫共享 member
c.getMember().toString(); // 拋出 ClassCastException!編譯器插入隱含轉型失敗

此破壞型別系統健全性。JSR-14 1.3 已修正為非法,Tiger 應同步禁止。

2. 泛型參數與基本型別

型別參數擦除為界限,界限不能是基本型別,故基本型別實例化擦除後無意義。例:Hashtable<String, int> 不合法,必須用 Hashtable<String, Integer> 並手動裝箱。自動裝箱/拆箱未納入 Tiger(期待 1.6)。

3. 型別轉換與 instanceof 中的「外露」參數

對外露參數轉型或 instanceof 產生 unchecked 警告。因擦除為界限,轉型實為向界限轉型,instanceof 檢查亦為界限檢查。例:

class C<T> implements Registry {
  Hashtable<Integer, T> values;
  public void register(Object o) { values.put(new Integer(counter), (T)o); } // 警告
}

若對 C<JFrame> 呼叫 register("test"),轉型表面成功,實則污染資料,後續計算錯誤或無聲失敗。嚴肅對待警告,該代碼區域型別檢查失效,靠自律。

雙面刃

泛型是健壯代碼利器,誤用則反害健壯性且難診斷修正。下期將介紹後兩大限制及納入泛型系統必面臨的問題。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved