首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Java 泛型通配符詳解:、、 異同與最佳實踐

     編輯:Java 綜合教學

Java 泛型通配符詳解:<? extends T>、<? super T>、<T extends T> 異同與最佳實踐

泛型通配符是 Java 類型系統中最令人困惑也最強大的部分。本文通過 Fruit → Apple/Orange 繼承體系,系統闡述六大核心問題。

類別定義

class Fruit {}
class Apple extends Fruit {}
class Orange extends Fruit {}

一、為何 List<Fruit> 不是 List<Apple> 的父類型?

兩大原因:

  1. 型別擦除:編譯後皆為 List,無繼承關係。
  2. 邏輯不安全:若允許 List<Fruit> list = new ArrayList<Apple>(),則可 list.add(new Orange()),破壞 List<Apple> 的型別承諾。

二、<? extends Fruit> 存在的必要性 —— 生產者

需求:方法同時接受 List<Fruit>、List<Apple>、List<Orange>。
解法:void process(List<? extends Fruit> list)

  • 表示:list 持有 Fruit 或其子類型,上界為 Fruit。
  • 只能讀(獲取),不能寫(添加):編譯器不知具體子類型,拒絕 add()(除 null)。
  • 適用場景:生產者——從集合取出元素處理。

三、<? super Fruit> 與 <? extends Fruit> 差異 —— 消費者

void addFruits(List<? super Fruit> list)

  • 表示:list 持有 Fruit 或其父類型,下界為 Fruit。
  • 只能寫,讀取只能作為 Object:確定元素至少是 Fruit,安全 add(new Apple())、add(new Fruit());獲取時類型擦除為 Object。
  • 適用場景:消費者——向集合放入元素。

PECS 原則:Producer Extends, Consumer Super。只讀用 extends,只寫用 super,既讀又寫不用通配符。

四、<? extends Fruit> vs <T extends Fruit>

語法位置用途
<T extends Fruit>類/方法宣告定義型別參數,方法內可用 T 宣告變數、返回值、參數
<? extends Fruit>參數化型別實參實例化泛型時指定上界,不可在程式碼中引用 ?
// 方法型別參數
public <E extends Fruit> void copy(List<E> src, List<E> dest) { ... }

// 通配符實參
public void print(List<? extends Fruit> list) { ... }

五、原生 List vs List<?>

  • List(原生型別):關閉泛型檢查,可任意 add,不安全,僅為相容舊代碼。
  • List<?>(無界通配符):表示「未知型別的 List」,禁止 add(除 null),讀取為 Object,類型安全。

建議:新代碼一律用 List<?> 代替原生 List。

六、自限定泛型 class A<T extends A<T>>

經典模式:Enum<E extends Enum<E>>、Comparable<T extends Comparable<T>>。

class Base<T extends Base<T>> {
    void set(T arg) { System.out.println("in Base"); }
}

class SubA extends Base<SubA> {}
class SubB extends Base<SubB> {}

// 用法
SubA a1 = new SubA(), a2 = new SubA();
a1.set(a2); // OK
// a1.set(new SubB()); // 編譯錯誤
// a1.set(new Base<>()); // 編譯錯誤

意義:基類方法參數/返回型別精確為具體子類型,實現「類型安全的鏈式呼叫」與「複製模式」。

總結速查表

List<?>
語法讀/寫典型場景關鍵字
<? extends T>讀/不可寫生產者、複製來源PECS - Extends
<? super T>寫/讀為 Object消費者、複製目標PECS - Super
<T extends Bound>完全可控泛型方法/類定義型別參數
讀為 Object/不可寫未知型別集合、工具方法無界通配符
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved