该问题的答案表明,当方法采用通配符通用类型时,可以访问或修改集合,但不能同时访问或修改集合。(凯西和伯特)
这是一个很合理的第一近似值,但并不完全正确。更正确的是:
您只能将null添加到,Collection<? extends Dog>
因为其add方法采用的参数? extends Dog
。每当调用方法时,都必须传递声明的参数类型的子类型的参数。但是对于参数类型? extends Dog
,如果表达式为则编译器只能确保参数为兼容类型null
。但是,您当然可以通过调用clear()
或来修改集合remove(Object)
。
另一方面,如果您从a读取Collection<? super Dog>
,则其迭代器具有return type ? super Dog
。也就是说,它将返回对象的某个未知超类型的子类型的对象Dog
。但是不同的是,Collection可以Collection<Object>
仅包含的实例String
。因此
for (Dog d : collection) { ... } // does not compile
因此,我们唯一知道的是返回了Object的实例,即,迭代此类Collection的唯一类型正确的方法是
for (Object o : collection) { ... }
但是可以从一个集合中读取内容,而您只是不知道将得到什么类型的对象。
我们可以轻松地将该观察结果概括为:
class G<T> { ... }
和
G<? extends Something> g;
我们只能将null传递给声明类型的方法参数T
,但是我们可以调用返回类型的方法T
,并为结果分配一个type变量Something
。
另一方面,对于
G<? super Something> g;
我们可以将任何类型的表达式传递Something
给具有声明类型的方法参数T
,并且可以调用具有返回类型的方法T
,但只能将结果赋给类型变量Object
。