如果Java String扩展了Object,那么为什么它不能传递给<! - ? extends Object - > type

时间:2017-04-25 18:28:10

标签: java string compiler-errors extends

例如,为什么以下不起作用?

Map<String, ? extends Object> table = new HashMap<>();
table.put("K", "V"); //Error V cannot be applied to ? extends String.

但是String必须扩展Object,为什么上面抛出编译错误?

我得到的IntelliJ错误是

Wrong 2nd Argument Type. Found 'java.lang.String'required: '? extends java.lang.Object'

然而,以下工作:

Map<String, ? super Object> table = new HashMap<>();
table.put("K", "V"); //Error V cannot be applied to ? extends String.

现在上面真的很奇怪。如何对Object类进行下限工作?

我的意思是不

? super Object

表示“未知是对象的超类”?

AFAIK Object位于Java类层次结构的根目录。

2 个答案:

答案 0 :(得分:9)

因为? extends Object并不意味着&#34;任何扩展Object的类型。&#34;这意味着&#34;某些特定的类型,我们不知道它是什么,只要它扩展了Object。&#34;差异很微妙,但很重要!

以下代码编译完全正确:

Map<String, Integer> stringToInteger = new HashMap<>();
Map<String, ? extends Object> stringToWildcard = stringToInteger;

有意义的是会编译。 stringToWildcard是一个地图,其值为&#34;某种类型......只要它扩展了对象&#34; - 和Integer是一种扩展对象的类型。

所以,考虑到这一点,想象一下你的table.put("K", "V")是否有效。我们可以这样做:

Map<String, Integer> stringToInteger = new HashMap<>();

Map<String, ? extends Object> stringToWildcard = stringToInteger;
stringToWildcard.put("K", "V");

Integer value = stringToInteger.get("K");

这会导致最后一行出现ClassCastException,因为字符串&#34; V&#34;无法转换为整数。

相反,编译器将禁止table.put("K", "V")。它告诉你的是:&#34;嘿,价值必须是某种特定的类型。我不知道那种类型是什么,除了它扩展了Object。但我不能让你输入一个String,因为我不知道该类型是否为String。&#34;

答案 1 :(得分:0)

这个项目解决了我的问题:

How can I add to List<? extends Number> data structures?

我在上面的解释中唯一的问题是形式的构造

List<? super T> myList;

帖子继续说你可以将任何类型T添加到myList或任何T&#39> 超类型实例。这似乎不准确。看起来您只能添加T或其任何子类型,因为T的子类型是T的任何超类型的自动子类型。那里有点含糊不清。