泛型的核心價值
- 將運行時 ClassCastException 前移至編譯期:編譯器拒絕類型不匹配代碼
- 消除強制類型轉換:
list.get(0) 直接返回 String 而非 Object
自定義泛型方法
public static <T> T test(T t) {
return t; // 占位符 T 由調用時實際參數類型推斷
}
// 調用
String s = test("abc"); // T 推斷為 String
Integer i = test(123); // T 推斷為 Integer(自動裝箱)
- 泛型參數慣用
T(Type)、E(Element)、K(Key)、V(Value)
- 基本類型無法作為類型參數,**必須使用包裝類**
集合泛型實戰
ArrayList<String> list = new ArrayList<>(); // 鑽石操作符 JDK 7+
list.add("aa"); list.add("bb");
// list.add(123); // 編譯報錯:類型不匹配
for (String str : list) {
System.out.println(str.toUpperCase()); // 無需強轉
}
類型擦除本質
- 泛型信息**僅存在於編譯階段**,字節碼中被擦除為原始類型(Raw Type)
ArrayList<String> 編譯後實際是 ArrayList,get() 返回 Object,編譯器自動插入 checkcast 指令
- 運行時無法區分
List 與 List
常見陷阱與應對
| 陷阱 | 原因 | 解決 |
無法創建泛型數組 new T[10] | 擦除後類型信息丟失 | 用 List<T> 或反射 Array.newInstance(clazz, size) |
| instanceof 檢查泛型 | 運行時無泛型信息 | 檢查原始類型:list instanceof List |
| 靜態成員引用類型參數 | 靜態屬於類,非實例 | 改為實例字段或方法局部變量 |
通配符與邊界
<? extends T>:上界通配符,**只讀**場景(生產者)
<? super T>:下界通配符,**只寫**場景(消費者)
- PECS 原則:**P**roducer **E**xtends,**C**onsumer **S**uper