預泛型時代:List list = new ArrayList(); list.add("A"); list.add(100); 取出時需強轉,運行期才發現 ClassCastException。**泛型將類型檢查前置到編譯期**,實現「編譯不報錯,運行不拋異常」。
List<String> 中 String 為 **類型實參**。interface List<E> 中 E 為 **類型形參**。List,泛型信息不進入字節碼(簽名除外)。public class Box<T> {
private T value;
public Box(T value) { this.value = value; }
public T get() { return value; }
public void set(T value) { this.value = value; }
}
// 使用
Box box = new Box<>("Hello");
String s = box.get(); // 無需強轉
public interface Repository<T, ID> {
T findById(ID id);
List<T> findAll();
T save(T entity);
}
public class Util {
// 靜態泛型方法
public static <T> List<T> asList(T... arr) {
return Arrays.asList(arr);
}
// 實例泛型方法
public <T> T first(Collection<T> c) {
return c.iterator().next();
}
}
// 調用:類型推導自動匹配
List nums = Util.asList(1, 2, 3);
String first = Util().first(List.of("a", "b"));
Box b1 = new Box<>("A");
Box b2 = new Box<>(1);
System.out.println(b1.getClass() == b2.getClass()); // true,運行期同一 Class 對象
// new T()、T[]、instanceof T、T.class 均非法
| 通配符 | 含義 | 能讀取 | 能寫入 | PECS 原則 |
|---|---|---|---|---|
<? extends Number> | Number 或其子類 | ✅ (作為 Number) | ❌ (除 null) | Producer Extends |
<? super Integer> | Integer 或其父類 | ❌ (只能作 Object) | ✅ (接受 Integer 及子類) | Consumer Super |
<?> | 任意類型 | ✅ (作 Object) | ❌ | 雙向只讀 |
public static void copy(List<? super T> dest, List<? extends T> src) {
for (T t : src) dest.add(t); // src 只讀,dest 只寫,完美匹配 PECS
}
Integer[] → Number[] 合法,運行期檢查存入類型。List → List **非法**。new List[10] 編譯錯誤。替代方案:List>
或 new ArrayList<>()[10](非泛型數組)。<T extends Number & Comparable<T>> // 多重界限
<T extends Comparable<? super T>> // 遞歸界限:自身可比較(Enum、String、包裝類均符合)
List ❌ → List ✅。static T field; ❌,泛型方法自帶類型參數 ✅。obj instanceof List ❌,用 instanceof List + 遍歷檢查。void m(List) 和 void m(List) 擦除後簽名相同,編譯錯誤。泛型通過 **編譯期類型參數化 + 運行期類型擦除** 實現類型安全與向後兼容。掌握 **PECS 原則、擦除後果、自定義泛型類/接口/方法、有界參數、避坑清單**,即可在 API 設計、集合框架擴展、框架開發中靈活運用泛型威力。