如果A extends X,
以下声明有效
List<? extends X> list = new ArrayList<A>();
似乎列表将包含扩展 X 的元素集合。因此,new A()
应该符合条件。
是的,它没有。这是为什么?
你几乎明白了。 List<? extends X>
表示“某种类型的列表(我实际上并不知道),它是 X 的子类型(或者可能是 X 本身)”。
问题是,例如,如果 X 是Number
. 然后List<? extends X>
表示List<Double>
orList<Integer>
或其他类型,您刚才说过您实际上并不知道。您不能将任何Number
内容插入List<Integer>
. 因此,由于您不知道列表元素的类型,因此您无法将任何内容插入到List<? extends Number>
. 但是,您可以从列表中检索值,并且可以保证列表中包含的任何值至少是Number
.
有关更多信息,请阅读第 28 条:使用有界通配符提高有效 Java中的 API 灵活性,第 2 版。Joshua Bloch (一本每个 Java 程序员都应该在他们的书架上拥有的书)。特别是,本项解释了助记符 PECS,意思是“生产者扩展,消费者超级”,这将帮助您记住 Java 泛型中的extends
和super
关键字的含义以及应该何时使用它们。
List<? extends X>
没有确定的类型。这意味着list
可以从一系列类型中分配变量,例如List<A>
, 也可以List<B>
(where B extends X
)。如果编译器允许您添加new A()
到这样的列表,您将添加一个A
to List<B>
。那将是类型安全的失败。
您正在创建一个泛型extends
类型的列表引用(变量)。这表明该列表可以包含具有X
作为超类的类的实例。但是,在创建列表的实际实例时,您将其限制为仅保存 class 的实例A
。这听起来不奇怪吗?