目录
在泛型代码中,问号(?)称为通配符,用来表示未知类型。通配符可以在多种情况下使用:如作为参数、字段或局部变量的类型;有时也可以作为返回类型。另外,通配符永远不会用作调用泛型方法、创建泛型类或超类型实例的类型参数。
为什么使用通配符?
在 Java 中,类和数组之间的对象关系是可以继承的,比如 Dog extends Animal,那么 Animal[] 与 Dog[] 就是兼容的。但是集合之间却不存在这种关系,也就是说 List<Animal> 不是List<Dog> 的父类,他们之间没有任何关系。那么为了建立两个集合之间的联系,就需要用到通配符。// 只是其中一部分原因
1、如何定义和使用上界通配符?
可以使用上界通配符来放宽对变量的限制。例如,你想编写一个方法,该方法适用于List<Integer>, List<Double> 和 List<Number>;就可以通过使用上界通配符来实现这一点。
声明一个上界通配符,需要使用通配符 ('?'),跟上 extends 关键字,然后再跟它的上界。比如,编写用于 Number 列表和 Number 子类型(如 Integer、Double 和 Float)的方法,可以指定 List<? extends Number>。List<? extends Number> 要比 List<Number> 对类型的限制更加宽松,因为 List<Number> 只匹配类型为 Number 的列表,而 List<? extends Number> 匹配类型为 Number 或其任何子类的列表。
例如下边的程序代码:
public static void process(List<? extends Foo> list) { /* ... */ }
上界通配符 <? extends Foo> 中的 Foo 匹配 Foo 类型和 Foo 的任何子类型。process() 方法可以访问类型为 Foo 的列表元素:
public static void process(List<? extends Foo> list) {
for (Foo elem : list) {
// ...
}
}
在 foreach 子句中,elem 变量迭代列表中的每个元素。在 elem 元素上可以使用 Foo 类中定义的任何方法。
如下,sumOfList() 方法返回列表中数字的和:
public static double sumOfList(List<? extends Number> list) {
double s = 0.0;
for (Number n : list)
s += n.doubleValue();
return s;
}
下面的代码,使用一个 Integer 对象列表,输出 sum = 6.0:
List<Integer> li = Arrays.asList(1, 2, 3);
System.out.println("sum = " + sumOfList(li));
Double 值列表可以使用相同的 sumOfList() 方法。下面的代码输出 sum = 7.0:
List<Double> ld = Arrays.asList(1.2, 2.3, 3.5);
System.out.println("sum = " + sumOfList(ld));
2、如何定义和使用无界通配符?