泛型讓「類型」成為參數,賦予 API 極致的複用性與類型安全。本文從聲明語法、實例化、原始類型、泛型方法、有界類型五大基石,構建完整知識體系。
class Box<T> { T value; } // 單一型別參數
interface Map<K, V> { ... } // 多型別參數,逗號分隔
標準命名:Element、Key、Value、Type、S/U/V (第 2/3/4 型別)
Box<String> box = new Box<>(); // Java 7+ 鑽石語法 <>
Box<List<String>> box2 = new Box<>(); // 型別參數可為參數化類型
注意:鑽石語法僅省略構造器型別參數,宣告端不可省略。
Box rawBox = new Box(); // 原始類型:無型別參數
Box<String> stringBox = new Box<>();
rawBox = stringBox; // 允許:參數化 → 原始 (無警告)
stringBox = rawBox; // 警告:unchecked conversion
@SuppressWarnings("unchecked")型別參數置於回傳型別前,作用域限於方法內:
public static <K, V> boolean compare(Pair<K,V> p1, Pair<K,V> p2) {
return p1.getKey().equals(p2.getKey()) && p1.getValue().equals(p2.getValue());
}
// 調用時編譯器自動推斷
boolean same = Util.compare(new Pair<>(1, "apple"), new Pair<>(2, "pear"));
<T extends Number> void inspect(T t) { ... } // 單一上界
<T extends Comparable<T> & Serializable> ... // 多重界限用 &
extends 兼具「繼承類」與「實現介面」語義List<Integer> 不是 List<Number> 的子類型!
List<Number> list = new ArrayList<Integer>(); // 編譯錯誤
List<? extends Number> list = new ArrayList<Integer>(); // 正確:使用通配符
但 ArrayList<String> 實現 List<String>,繼承 Collection<String>,型別參數不變時繼承關係保留。