例如,为什么以下不起作用?
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类层次结构的根目录。
答案 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的任何超类型的自动子类型。那里有点含糊不清。