泛型核心動機
編譯期指定容器持有類型,由編譯器保證類型安全,消除強制轉換與 ClassCastException 風險。
類型擦除:泛型的「阿喀琉斯之踵」
- 運行期泛型類型信息被擦除,
List<String> → List(原始類型)
- 擦除至第一個邊界(無邊界則擦除至
Object)
- 後果:無法
new T()、instanceof T、new T[10]、重載泛型方法、捕獲泛型異常
- 補償:顯式傳遞
Class<T> 類型標籤(Type Token)
邊界
<T extends Comparable<T>> // T 必須實現 Comparable<T>
<T extends Base & Interface> // 多重邊界,類在前,接口在後
- 邊界允許調用邊界類型的方法
extends 在泛型中表示「受限於」,非繼承
通配符
| 語法 | 含義 | 讀/寫能力 |
<? extends T> | T 或其子類(上界) | 可讀(取出 T),不可寫(除 null) |
<? super T> | T 或其父類(下界) | 可寫(放入 T),讀出只能作 Object |
<?> | 無界通配符 | 相當於 <? extends Object>,僅能讀 Object、寫 null |
PECS 原則:Producer Extends, Consumer Super
捕獲轉換
編譯器將無界通配符捕獲為具體佔位類型,允許在方法內部安全操作該具體類型。
自限定類型
// Curiously Recurring Generics (CRG)
class Base<T extends Base<T>> { ... }
class Derived extends Base<Derived> { ... }
- 基類用衍生類型作參數,實現「類型安全的鏈式調用」
- 自限定:
class Self<T extends Self<T>> 強制類型參數為自身
- 應用:Builder 模式、比較器鏈、枚舉類型安全
動態類型安全:Collections.checkedList
- 運行期檢查插入類型,違規即拋
ClassCastException(而非取出時)
- 兼容非泛型舊代碼,防止「堆污染」
泛型與異常
- 不能捕獲泛型異常:
catch (E e) 非法
- 泛型類不能繼承
Throwable
- 但可在
throws 中使用類型參數
Mixin 模式與裝飾器對比
- C++ 模板可實現 Mixin(
template<class T> class Mixin : public T)
- Java 擦除導致無法繼承類型參數
- 替代:接口組合 / 動態代理 / 裝飾器模式
潛在類型
只要求對象擁有特定方法子集,不要求實現特定接口。Java 泛型屬於顯式類型系統,靈活度略低於動態語言的鴨子類型,但提供編譯期保證。
- 上一篇文章: Solr 定時增量索引報錯 NullPointerException 根因分析與修復方案
- 下一篇文章: JavaMail + Apache James 郵件系統完整搭建與發送帶附件郵件實戰
Copyright ©
程式碼之家 All Rights Reserved