通配符(Wildcard)是 Java 泛型中非常重要的一个特性,它允许我们处理未知类型的数据。
通配符(?
)是一种特殊的泛型符号,用于表示某种未知类型。它通常出现在方法参数、返回值或变量声明中,用来增强代码的灵活性。
public void printList(List> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
在这个例子中,List>
表示一个 List
,但它的具体类型未知(可以是任何类型)。通过使用通配符,这个方法可以接受任意类型的 List
。
Java 中的通配符分为三种:无界通配符、上界通配符和下界通配符。它们的作用不同,适用于不同的场景。
>
public void printList(List> list) {
for (Object obj : list) {
System.out.println(obj);
}
}
// 使用
List stringList = Arrays.asList("A", "B");
List intList = Arrays.asList(1, 2, 3);
printList(stringList); // 可以传入 List
printList(intList); // 也可以传入 List
在这个例子中,List>
表示可以接受任意类型的 List
,但我们只能将其元素视为 Object
类型(因为具体类型未知)。
extends T>
T
或其子类。public void printNumbers(List extends Number> list) {
for (Number num : list) {
System.out.println(num);
}
}
// 使用
List intList = Arrays.asList(1, 2, 3);
List doubleList = Arrays.asList(1.1, 2.2, 3.3);
printNumbers(intList); // 可以传入 List
printNumbers(doubleList); // 也可以传入 List
在这个例子中,List extends Number>
表示可以接受 Number
或其子类(如 Integer
、Double
等)的列表。由于我们知道所有元素都是 Number
的子类,因此可以安全地读取它们作为 Number
类型。
注意:使用上界通配符时,不能向集合中添加元素(除了
null
),因为编译器无法确定具体类型。
List extends Number> numbers = new ArrayList<>();
numbers.add(new Integer(1)); // 编译错误
numbers.add(new Double(1.1)); // 编译错误
numbers.add(null); // 允许,因为 null 是所有类型的子类
super T>
T
或其父类。public void addNumbers(List super Integer> list) {
list.add(1);
list.add(2);
list.add(3);
}
// 使用
List numberList = new ArrayList<>();
addNumbers(numberList); // 可以传入 List
List
在这个例子中,List super Integer>
表示可以接受 Integer
或其父类(如 Number
、Object
等)的列表。由于我们知道 Integer
是这些类型的子类,因此可以安全地向集合中添加 Integer
类型的元素。
注意:使用下界通配符时,读取数据时只能将其视为
Object
类型,因为具体类型未知。
List super Integer> numbers = new ArrayList<>();
numbers.add(1); // 允许写入 Integer
Object obj = numbers.get(0); // 只能读取为 Object
上界通配符常用于读取数据的场景,例如计算集合中的最大值、打印集合内容等。
public > T max(List extends T> list) {
if (list.isEmpty()) {
throw new IllegalArgumentException("List is empty");
}
T max = list.get(0);
for (T item : list) {
if (item.compareTo(max) > 0) {
max = item;
}
}
return max;
}
// 使用
List intList = Arrays.asList(1, 5, 3);
System.out.println(max(intList)); // 输出 5
在这个例子中,List extends T>
允许我们接受任何 T
或其子类的列表,而 Comparable super T>
则允许我们比较 T
或其父类的对象。
下界通配符常用于写入数据的场景,例如向集合中添加元素。
public void copy(List super Integer> dest, List extends Number> src) {
for (Number num : src) {
dest.add((Integer) num.intValue());
}
}
// 使用
List intList = new ArrayList<>();
List numberList = Arrays.asList(1.1, 2.2, 3.3);
copy(intList, numberList);
System.out.println(intList); // 输出 [1, 2, 3]
在这个例子中,List super Integer>
允许我们将 Integer
类型的元素添加到目标集合中,而 List extends Number>
则允许我们从源集合中读取 Number
类型的元素。
通配符类型 | 含义 | 场景 |
---|---|---|
> |
表示任意类型 | 不关心具体类型,只读操作 |
extends T> |
表示 T 或其子类 |
读取数据,确保数据是 T 或其子类 |
super T> |
表示 T 或其父类 |
写入数据,确保数据是 T 或其父类 |
Collections
类)中有很多使用通配符的例子,可以帮助你加深理解。