文章目錄
- 135. Java 泛型 - 無界通配符 (`?`)
- **1. 什么是無界通配符 (`?`)?**
- **2. 為什么使用無界通配符?**
- **3. 示例:使用 `?` 處理任意列表**
- **? 錯誤示例**
- **? 正確示例**
- **4. 為什么 `List<Object>` 和 `List<?>` 不一樣?**
- **? 錯誤示例**
- **5. 適用場景**
- **6. 結論**
135. Java 泛型 - 無界通配符 (?
)
在 Java 泛型中,無界通配符 (?
) 允許表示任何類型,使代碼更加通用。
本篇將詳細講解無界通配符的概念,并結合示例幫助理解。
1. 什么是無界通配符 (?
)?
無界通配符 ?
代表“未知類型”,它可以用于泛型類或泛型方法,使其適用于任意類型。
例如:
List<?> list;
list
可以接受List<String>
、List<Integer>
、List<Double>
等任何類型的List
。- 但由于
?
代表未知類型,無法向list
中添加元素(除了null
)。
2. 為什么使用無界通配符?
無界通配符適用于以下兩種情況:
- 僅使用
Object
類的方法,而不需要特定類型的方法(如toString()
、equals()
、hashCode()
)。 - 方法的邏輯不依賴于泛型類型參數,如
List.size()
或List.clear()
。
? 無界通配符的語法
List<?> list = new ArrayList<String>();
- 這里
list
可以引用任何類型的List
(List<Integer>
、List<Double>
等)。 - 但是,我們不能向
list
添加元素(除了null
)。
3. 示例:使用 ?
處理任意列表
📌 需求:編寫一個方法,能夠打印任何類型的 List
,包括 List<String>
、List<Integer>
、List<Double>
等。
? 錯誤示例
以下代碼無法打印 List<Integer>
,因為 List<Integer>
不是 List<Object>
的子類:
public static void printList(List<Object> list) { // ? 只能接受 List<Object>for (Object elem : list)System.out.println(elem);
}public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3);printList(numbers); // ? 編譯錯誤
}
🔍 為什么?
List<Integer>
不是List<Object>
的子類(因為泛型是不協變的)。- Java 泛型中的
List<T>
是不可變更類型的,即List<Integer>
和List<Object>
沒有繼承關系。
? 正確示例
import java.util.Arrays;
import java.util.List;public class UnboundedWildcard {public static void printList(List<?> list) { // ? 適用于任何 List 類型for (Object elem : list) { // ? 安全讀取元素System.out.print(elem + " ");}System.out.println();}public static void main(String[] args) {List<Integer> numbers = Arrays.asList(1, 2, 3);List<String> words = Arrays.asList("Hello", "World");List<Double> decimals = Arrays.asList(1.1, 2.2, 3.3);printList(numbers); // 輸出: 1 2 3 printList(words); // 輸出: Hello World printList(decimals); // 輸出: 1.1 2.2 3.3}
}
🔍 解析
printList(List<?>)
可以接受任何List<T>
,如List<Integer>
、List<String>
、List<Double>
等。Object elem
安全讀取list
的元素,因為所有 Java 對象最終都繼承自Object
。- 但我們不能向
list
添加元素(除了null
)。
4. 為什么 List<Object>
和 List<?>
不一樣?
在 Java 泛型中,List<Object>
和 List<?>
并不相同:
List<Object>
只能存儲Object
及其子類,但不能存儲Integer
、String
,因為List<Integer>
不是List<Object>
的子類。List<?>
可以存儲任何類型的List
,但由于類型未知,無法向List<?>
添加元素(除了null
)。
? 錯誤示例
List<?> unknownList = new ArrayList<Integer>();
unknownList.add(5); // ? 編譯錯誤
unknownList.add("Hello"); // ? 編譯錯誤
unknownList.add(null); // ? 允許
🔍 為什么?
unknownList
可以引用List<Integer>
、List<String>
、List<Double>
,但Java 無法確定具體的類型,所以不允許添加元素。- 但**
null
可以插入**,因為null
適用于任何類型。
5. 適用場景
? 適用于不關心具體類型的 List
(如通用的 printList
方法)。
? 適用于使用 Object
方法的情況(如 toString()
、size()
、clear()
)。
? 適用于泛型方法,使代碼更加靈活。
6. 結論
? ?
表示“未知類型”,可以匹配任意泛型類型。
? List<?>
可以存儲 List<T>
的任何類型,但不能添加元素(除了 null
)。
? List<?>
與 List<Object>
不同,前者適用于任何 List<T>
,而后者僅適用于 List<Object>
。
? 使用 ?
讓代碼更加通用,提高可復用性。
🎯 記住口訣:
- 無界通配符
?
適用于“只讀”數據(與Object
兼容)。 List<?>
不能添加元素,避免類型不安全問題。List<?>
適用于“泛型無關”的方法,如size()
、clear()
和toString()
。
🚀 學會 ?
,讓你的 Java 泛型代碼更靈活!