文章目錄
- 134. Java 泛型 - 上限通配符 (`? extends T`)
- **1. 什么是上限通配符 (`? extends T`)?**
- **2. 為什么使用 `? extends T`?**
- **3. 示例:使用 `? extends T` 進行數據讀取**
- **? 示例 1:計算數值列表的總和**
- **4. 注意事項:為什么不能向 `List<? extends T>` 添加元素?**
- **? 錯誤示例**
- **5. 適用場景**
- **6. 結論**
134. Java 泛型 - 上限通配符 (? extends T
)
在 Java 泛型中,我們可以使用上限通配符 (? extends T
) 來放寬對變量的限制,使方法能夠適用于某個類型及其所有子類型。
讓我們深入了解它的概念,并通過示例加深理解。
1. 什么是上限通配符 (? extends T
)?
在泛型中,我們可以使用 ? extends T
來表示“某個類 T 及其所有子類”。
- 其中,
extends
在這里不僅表示類的繼承,也可以用于接口的實現。 - 這在處理同一類層級中的不同泛型類型時非常有用。
? 語法
List<? extends Number> list;
list
可以接受List<Number>
、List<Integer>
、List<Double>
、List<Float>
等。- 但是,不能向
list
中添加元素(除了null
),因為 Java 無法確定具體的子類型。
2. 為什么使用 ? extends T
?
假設我們需要編寫一個方法,它能夠接受 List<Integer>
、List<Double>
和 List<Number>
,而不需要為每個具體類型單獨編寫方法。
使用 ? extends T
可以讓方法適用于T 及其子類,避免代碼重復,增強通用性。
3. 示例:使用 ? extends T
進行數據讀取
📌 需求:編寫一個方法計算 List<Number>
及其子類(如 Integer
、Double
)的總和。
? 示例 1:計算數值列表的總和
import java.util.Arrays;
import java.util.List;public class UpperBoundWildcard {public static double sumOfList(List<? extends Number> list) {double sum = 0.0;for (Number n : list) {sum += n.doubleValue(); // ? 可以安全地調用 Number 的方法}return sum;}public static void main(String[] args) {List<Integer> integers = Arrays.asList(1, 2, 3);System.out.println("Sum of integers: " + sumOfList(integers)); // 輸出: 6.0List<Double> doubles = Arrays.asList(1.2, 2.3, 3.5);System.out.println("Sum of doubles: " + sumOfList(doubles)); // 輸出: 7.0}
}
🔍 解析
sumOfList(List<? extends Number> list)
接受Number
及其所有子類。list
可以是List<Integer>
、List<Double>
、List<Float>
等。n.doubleValue()
? 安全調用Number
類的方法,因為所有Number
的子類都繼承了doubleValue()
。
4. 注意事項:為什么不能向 List<? extends T>
添加元素?
? 在 List<? extends T>
中,我們無法添加元素(除了 null
),否則會導致編譯錯誤。
? 錯誤示例
List<? extends Number> list = new ArrayList<Integer>();
list.add(5); // ? 編譯錯誤
list.add(3.14); // ? 編譯錯誤
🔍 為什么?
list
可能是List<Integer>
,但list.add(3.14)
試圖添加Double
,這會破壞List<Integer>
的類型安全性。- Java 編譯器無法確保
list
的實際類型,因此不允許添加元素,但可以安全讀取元素(因為所有元素都是Number
)。
? 解決方案
List<Number> list = new ArrayList<>();
list.add(5); // ? 允許
list.add(3.14); // ? 允許
如果需要向列表添加元素,就不能使用 ? extends T
,而應該使用具體類型 T
。
5. 適用場景
? 適用于只“讀取”數據的情況(Producer)。
? 適用于同一繼承層級中的多個泛型類型(如 Number
的子類)。
? 適用于通用方法,使代碼更具靈活性。
6. 結論
? ? extends T
表示 T 及其所有子類,適用于“讀取”數據的情況。
? 無法向 List<? extends T>
添加元素,因為 Java 無法確保其實際類型。
? 使用 ? extends T
可以增強代碼的通用性,避免代碼重復。
? 典型用法:計算數值列表的總和,遍歷對象并調用父類方法。
🎯 記住口訣:
- Producer Extends (
? extends T
) 👉 用于“讀取”數據 - Consumer Super (
? super T
) 👉 用于“寫入”數據
🚀 泛型讓 Java 代碼更靈活,學會 ? extends T
,讓你的代碼更通用!