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

时间:2016-01-30 06:53:01

标签: java list wildcard

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

给定一段代码给我编译时错误。我不明白为什么我不能在列表中添加字符串。 但代码意味着我们可以在列表中添加String类对象及其派生类对象 我仍然得到错误原因

3 个答案:

答案 0 :(得分:2)

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

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");

答案 1 :(得分:1)

这将有效:

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

答案 2 :(得分:1)

基本上List<? extends String>是未知类型的List,所有已知的是此类型扩展String。变量包含List<String>

的实例并不重要

现在String是final,所以没有子类......所以让我们考虑一下:

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

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

但你知道这是对的吗? 嗯,编译器没有,也没有预测未知类型和你实例化的逻辑连接,因为通常你可以在运行时更改该变量。

在乐观上命名为More Fun with Wildcards的教程中存在一个类似的示例,其中方法接受(Set<T>, T),并且使用(Set<?>, String)通过Set<?>变量进行非法调用包含Set<String>的实例。尽管添加了extends

,但问题仍然存在