Java 泛型的類型推斷機制與通配符系統,是編寫優雅、安全 API 的核心工具。本文從編譯器推斷邏輯、通配符上下界、PECS 原則三個維度,系統梳理進階用法。
編譯器根據實參類型自動推導型別參數,無需顯式指定:
static <T> T pick(T a1, T a2) { return a2; }
Serializable s = pick("d", new ArrayList<String>()); // 推斷為 Serializable
Java 7+ 支援鑽石語法 <> 省略構造器型別參數,Java 8 進一步將方法參數納入目標類型推斷範圍:
Map<String, List<String>> map = new HashMap<>(); // 鑽石語法
processStringList(Collections.emptyList()); // Java 8 編譯通過
<? extends T>表示 T 及其子類型,適用於「只讀」場景(In 變量):
public void process(List<? extends Number> list) {
Number n = list.get(0); // 安全讀取
// list.add(new Integer(1)); // 編譯錯誤:不可寫入
}
<? super T>表示 T 及其父類型,適用於「只寫」場景(Out 變量):
public void addIntegers(List<? super Integer> list) {
list.add(1); // 安全寫入
// Number n = list.get(0); // 僅能作為 Object 讀取
}
<?>等同於 <? extends Object>,僅能插入 null,適合調用與型別無關的方法(如 size()、clear())。
當編譯器無法確認型別安全時,可透過私有泛型輔助方法實現捕獲:
void foo(List<?> i) { fooHelper(i); }
private <T> void fooHelper(List<T> l) { l.set(0, l.get(0)); }
extendssuper