在 List 中使用通配符时出现编译时错误

compile time error while using wildcard in List

List<? extends String> list = new Arraylist<String>();
list.add("foo");

给定的一段代码给出了编译时间 error.i 不明白为什么我不能在列表中添加字符串。 但是代码意味着我们可以在列表中添加 String class 对象及其派生的 class 对象 我仍然收到错误为什么

List<?> 仅当您不关心项目的数据类型并且对获取列表大小等操作感兴趣时才应使用。

例如,

public int getSize(List<?> itemList) {
     return itemList.size();
}

它更像是一个 Read Only 列表。

如果您打算创建包含 String 项的新列表,则应使用以下内容。

List<String> list = new Arraylist<>();
list.add("foo");

或者,您可以使用这个:

List<Object> list = new Arraylist<>();
list.add("foo");

这会起作用:

List<? super String> list = new ArrayList<String>();
list.add("foo");

然后您的编译器现在将调用者传递 String 或超类型的对象列表。

当你说 <? extends String> 时,它意味着它可以是扩展 String 的任何类型。这意味着有人可以通过 List 并且它会接受它。

另请看这里: Difference for <? super/extends String> in method and variable declaration

本质上List<? extends String>是一个未知类型的List,只知道这个类型扩展了String。变量包含 List<String>.

的实例并不重要

现在 String 是最终的,所以没有子class...所以让我们考虑一下:

List<? extends A> list = new ArrayList<A>();

其中 A 是一些 class 和一个子 class B。使用时,List<? extends A> 类型的变量可能是 List<B> 的实例。我们不能向其中添加 A,因为 A 可能不是 B.

但你知道它会是对的吗? 嗯,编译器不会,它也不会预测未知类型与您实例化的内容之间的逻辑联系,因为通常您可能会在运行时更改该变量。

乐观地命名为 More Fun with Wildcards 的教程中存在一个类似的例子,其中一个方法接受 (Set<T>, T) 并且使用 (Set<?>, String) 预先设置一个非法调用,尽管 Set<?> 变量包含 Set<String> 的实例。这里的问题是一样的,尽管添加了 extends.