文章目錄
- 136. Java 泛型 - 下限通配符 (`? super T`)
- **1. 什么是下限通配符 (`? super T`)?**
- **2. 為什么使用下限通配符?**
- **3. 示例:使用 `? super Integer` 允許添加 `Integer`**
- **? 正確示例**
- **4. 為什么 `List<? super Integer>` 和 `List<Integer>` 不一樣?**
- **? 錯誤示例**
- **5. 適用場景**
- **6. `? extends T` vs `? super T`**
- **7. 結論**
136. Java 泛型 - 下限通配符 (? super T
)
在 Java 泛型中,下限通配符 (? super T
) 允許指定某個類型的超類,使代碼更具靈活性。
本篇將詳細介紹下限通配符的概念,并結合示例幫助理解其應用。
1. 什么是下限通配符 (? super T
)?
下限通配符 ? super T
表示T 類型或 T 的任意超類,即:
List<? super Integer>
可以存儲Integer
及其所有父類(如Number
、Object
)。- 但由于類型不確定,讀取元素時只能賦值給
Object
。
? 下限通配符的語法
List<? super Integer> list;
list
可以接受List<Integer>
、List<Number>
、List<Object>
。- 可以安全地向
list
添加Integer
類型的元素。
2. 為什么使用下限通配符?
下限通配符 ? super T
適用于:
- 希望向集合中添加
T
類型的元素(T
及其父類)。 - 方法的邏輯僅依賴
T
的超類,而不需要具體的T
子類信息。 - 泛型方法中,確保集合能接收更廣泛的類型范圍。
3. 示例:使用 ? super Integer
允許添加 Integer
📌 需求:編寫一個方法,向 List
中添加 Integer
值,支持 List<Integer>
、List<Number>
和 List<Object>
。
? 正確示例
import java.util.List;
import java.util.ArrayList;public class LowerBoundWildcard {public static void addNumbers(List<? super Integer> list) { // ? 適用于 Integer 及其超類for (int i = 1; i <= 10; i++) {list.add(i); // ? 安全添加 Integer}}public static void main(String[] args) {List<Integer> intList = new ArrayList<>();List<Number> numList = new ArrayList<>();List<Object> objList = new ArrayList<>();addNumbers(intList); // ? 可以傳入 List<Integer>addNumbers(numList); // ? 可以傳入 List<Number>addNumbers(objList); // ? 可以傳入 List<Object>System.out.println(intList); // 輸出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]System.out.println(numList); // 輸出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]System.out.println(objList); // 輸出: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]}
}
🔍 解析
addNumbers(List<? super Integer>)
可以接受List<Integer>
、List<Number>
、List<Object>
。- 可以安全地向
list
添加Integer
,因為Integer
一定是? super Integer
允許的類型。 - 但無法保證從
list
讀取的數據類型(只能作為Object
處理)。
4. 為什么 List<? super Integer>
和 List<Integer>
不一樣?
在 Java 泛型中:
List<Integer>
僅適用于Integer
類型,無法存儲Number
或Object
。List<? super Integer>
可以存儲Integer
及其超類,如Number
和Object
,但無法確定列表存儲的具體類型。
? 錯誤示例
List<? super Integer> list = new ArrayList<Number>();
Number num = list.get(0); // ? 編譯錯誤
Integer i = list.get(0); // ? 編譯錯誤
Object obj = list.get(0); // ? 只能賦值給 Object
🔍 為什么?
- Java 只保證
list
里的元素是Integer
的某個超類,但無法確定具體是什么類型。 - 只能讀取為
Object
,避免類型轉換錯誤。
5. 適用場景
? 適用于“只寫”數據的情況(向列表添加 T
類型數據)。
? 適用于泛型方法,提高靈活性(使方法接受 T
及其超類)。
? 適用于需要更廣泛兼容性的集合(如 List<Number>
可以接收 Integer
)。
6. ? extends T
vs ? super T
通配符 | 適用情況 | 讀取元素 | 添加元素 |
---|---|---|---|
? extends T | 適用于只讀場景(數據讀取) | ? 可以讀取為 T | ? 不能添加元素(除了 null ) |
? super T | 適用于只寫場景(數據存儲) | ? 只能讀取為 Object | ? 可以添加 T 類型的數據 |
7. 結論
? ? super T
表示某個類型 T
或 T
的超類。
? 適用于“寫入數據”場景,確保方法能接收 T
及其超類的列表。
? 不能保證讀取的數據類型,只能作為 Object
處理。
? 適用于泛型方法,使代碼更加靈活和通用。
🎯 記住口訣:
? extends T
適用于“讀取”數據(如sum(List<? extends Number>)
)。? super T
適用于“寫入”數據(如addNumbers(List<? super Integer>)
)。- 使用
? super T
,讓 Java 泛型更靈活,兼容更多類型! 🚀