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

Java 泛型通配符深度解析:上界、下界與無限定通配符的實戰指南

     編輯:Java 綜合教學

Java 泛型通配符深度解析:上界、下界與無限定通配符的實戰指南

泛型通配符是 Java 類型系統中最靈活也最容易混淆的部分。本文通過對比 <T extends E> 與 <? extends E>、<? super E> 的異同,結合容器類實戰場景,徹底講清「什麼時候用通配符、什麼時候用類型參數、為什麼這樣用」。

一、從一個實際問題說起:如何將 Integer 集合添加到 Number 集合?

// 使用類型參數(啰嗦)
public <T extends E> void addAll(DynamicArray<T> c) {
    for (int i = 0; i < c.size; i++) add(c.get(i));
}

// 使用上界通配符(簡潔)
public void addAll(DynamicArray<? extends E> c) {
    for (int i = 0; i < c.size; i++) add(c.get(i));
}

兩種寫法效果相同,但通配符版本:

  • 無需聲明類型參數 <T>,方法簽名更簡潔。
  • 直接表達「E 或 E 的某個子類型」,語義更清晰。

二、核心區別:類型參數聲明 vs 類型參數實例化

三、通配符的「只讀」本質:為什麼不能寫入?

DynamicArray<Integer> ints = new DynamicArray<>();
DynamicArray<? extends Number> nums = ints; // 合法:上界通配符

nums.add(100);        // 編譯錯誤!
nums.add(new Double(1.0)); // 編譯錯誤!
nums.add(new Object());    // 編譯錯誤!

原因:? extends Number 表示「某個具體的 Number 子類型」,但編譯器不知道具體是哪個。允許寫入會破壞類型安全(如向 Integer 列表寫入 Double)。

四、無限定通配符 <?>:最寬鬆的只讀視圖

// 原版:只能寫入完全相同類型
public void copyTo(DynamicArray<E> dest) { ... }

// 改進:使用下界通配符,允許寫入 E 的父類型容器
public void copyTo(DynamicArray<? super E> dest) {
    for (int i = 0; i < size; i++) dest.add(get(i));
}

// 使用示例
DynamicArray<Integer> ints = ...;
DynamicArray<Number> nums = ...;
ints.copyTo(nums); // 合法!Integer 寫入 Number 容器

? super E 表示「E 的某個父類型」。既然容器能裝父類型,裝子類型當然安全。

場景 2:靈活比較——Comparable/Comparator 的經典應用

  

七、JDK 集合框架中的經典用法

// Collections 工具類
public static <T extends Comparable<? super T>> void sort(List<T> list)
public static <T> void sort(List<T> list, Comparator<? super T> c)
public static <T> void copy(List<? super T> dest, List<? extends T> src)
public static <T> T max(Collection<? extends T> coll, Comparator<? super T> comp)

完美體現:讀取用 extends,寫入用 super,比較用 super,拷貝 src 用 extends、dest 用 super。

八、小結

  • <?>、<? extends E>:靈活讀取,可用類型參數替代,但通配符更簡潔。
  • <? super E>:靈活寫入與比較,無法用類型參數替代,是泛型類型系統表達力的關鍵補充。
  • 實戰原則:公共 API 優先用通配符簡化簽名,內部實現用類型參數保證類型安全。

掌握通配符,是寫出優雅、健壯、可復用泛型代碼的關鍵一步。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
形式位置含義
<T extends E>類定義後、方法返回值前聲明一個類型參數 T,T 是 E 的子類型
<? extends E>泛型變量聲明處(實例化時)實例化類型參數為「E 或 E 的某個未知子類型」
場景推薦形式理由
只需讀取,類型無依賴<?> / <? extends E>簡潔、可讀性強、接受更廣類型
需要寫入容器<? super E>唯一能實現安全寫入的形式
類型參數之間有依賴關係<T>, <S extends T>通配符無法表達多參數依賴
返回值依賴類型參數<T>通配符無法在返回類型中引用
內部實現需要類型安全操作公共 API 用通配符,內部調用類型參數方法兼顧簡潔與類型安全