9.3.1 使用类型通配符

9.3.1 使用类型通配符

为了表示各种泛型List的父类,可以使用类型通配符,类型通配符是一个问号(?),将一个问号作为类型实参传给List集合,写作:List<?>(意思是元素类型未知的List)。这个问号(?)被称为通配符,它的元素类型可以匹配任何类型。可以将上面方法改写为如下形式:

1
2
3
4
5
6
public void test(List<?> c){
for (int i= 0;i < c.size(); i++)
{
System.out.println(c.get(i));
}
}

现在使用任何类型的List来调用它,程序依然可以访问集合c中的元素,其类型是Object,这永远是安全的,因为不管List的真实类型是什么,它包含的都是Object

通配符?可以作为任意泛型形参的实参

上面程序中使用的List<?>,其实这种写法可以适应于任何支持泛型声明的接口和类,比如写成Set<?>Collection<?>Map<?,?>
但这种带通配符的List<?>仅表示它是各种泛型List的父类,并不能把元素加入到其中。例如,如下代码将会引起编译错误:

1
2
3
List<?> list= new ArrayList<String>();
//下面程序引起编译错误
list.add(new Object());

因为程序无法确定c集合中元素的类型,所以不能向其中添加对象。根据前面的List<E>接口定义的代码可以发现:add()方法有类型参数E作为集合的元素类型,所以传给add的参数必须是E类的对象或者其子类的对象。但因为在该例中不知道E是什么类型,所以程序无法将任何对象”丢进”该集合。唯一的例外是null,因为**null是所有引用类型的实例**。
另一方面,程序可以调用get()方法来返回List<?>集合指定索引处的元素,其返回值是一个未知类型,但可以肯定的是,它总是一个Object。因此,把get()的返回值赋值给一个Object类型的变量,或者放在任何希望是Object类型的地方都可以。