7. 通配符
通配符,即 “?”,用来表示未知类型。
通配符可用作各种情况:作为参数,字段或局部变量的类型;有时也作为返回类型;通配符从不用作泛型方法调用、泛型类实例创建或超类型的类型参数。
7.1 上限有界的通配符
使用上限通配符来放宽对变量的限制。
声明上限通配符的语法:<? extends 上限>
举个例子:
public static double sumOfList(List<? extends Number> list) {
double s = 0.0;
for (Number n : list)
s += n.doubleValue();
return s;
}
这里 上线通配符为
7.2 无界通配符
使用通配符 “?” 指定无界通配符类型,例如 List<?>
,称为未知类型的列表。
无界通配符有两种适用场景:
- 当前正在编写可以借由 Object 类中的方法来实现的方法。
- 使用泛型类中不依赖于类型参数的方法时,如 List.size()、list.clear() 等;实际上,经常使用 Class
public static void printList(List<Object> list) {
for (Object elem : list)
System.out.println(elem + " ");
System.out.println();
}
如果只是希望打印 Object 列表,那这个方法可行;但是如果目标是打印任何类型的列表,那这个方法就不行了,它无法输出 List<Integer>
、List<Double>
等等,因为这些都不是 List<Object>
的子类型。
解决上述问题,就需要使用 List
public static void printList(List<?> list) {
for (Object elem: list)
System.out.print(elem + " ");
System.out.println();
}
这样,对于任何具体类型 A,List<A>
都是 List<?>
的子类型,于是可以用该方法打印任何类型的列表。
7.3 下限有界通配符
上限有界通配符将未知类型限制为该类型的特定类型或子类型,并使用 extends 关键字表示;类似的,下限有界通配符将位置类型限制为该类型的特定类型或超类型;
下限有界通配符的语法:<? super 下限>
注意:上限有界 和 下限有界 不能同时指定。
举个例子:
public static void addNumbers(List<? super Integer> list) {
for (int i = 1; i <= 10; i++) {
list.add(i);
}
}
在这个例子中,下限有界通配符是
7.4 通配符和子类型
在 5.1 泛型类和子类型 小节中,我们讲到泛型类或接口并不仅仅因为它们的类型之间存在关系而相互关联。
比如 Integer 是 Number 的子类型,但是 List<Integer>
和 List<Number>
却没什么关系,二者不过是有一个公共符类 List
List<? extends Integer> intList = new ArrayList<>();
List<? extends Number> numList = intList; // OK. List<? extends Integer> is a subtype of List<? extends Number>
因为 Integer 是 Number 的子类型,并且 numList 是一个 Number 对象的列表,所以现在 intList 和 numList 之间存在关联了。下图展示了使用上限和下限有界通配符声明的多个 List 类之间的关系:(箭头指向的是父类型)
7.5 通配符捕获和帮助方法
某些情况下,编译期会推断出通配符的类型。例如,列表定义为 List
import java.util.List;