泛型 <? super> 通配符

5
我想知道以下代码为什么不起作用:

我在想,为什么下面的代码不起作用:

Collection <? super String> col = new ArrayList<String>();
col.add(new Object());// does not compile
col.add("yo!");// compiles indeed;

如果类型是<? super String>,它可以包含任何超类(包括String)的内容,对吗?

4
<? super String> 只能添加字符串类型。Object 不一定是字符串类型。尝试执行以下代码:Object myObj = new String(); 这段代码应该可以正常工作。 - Maroun
1
不,任何继承自String的东西。这意味着它的超类是String。 - m0skit0
@m0skit0 那就是我感到困惑的地方。谢谢。 - Rollerball
@m0skit0 哎呀,为什么我尝试执行 <? super String> col = new ArrayList<Object>(); 时它能够编译通过!但是 Object 并不是 String 的子类啊!这些泛型真是让人头疼。 - Rollerball
抱歉,我的错,看看Marko的答案。 - m0skit0
请参考以下链接:https://dev59.com/vmjWa4cB1Zd3GeqPu-Tv#12605337。 - Brian
2个回答

15

Collection<? super String>,这与你的直觉相反,并不意味着“包含类型为String或其超类型的对象的集合”。它意味着“col将是一个持有某一确定类型的集合,该类型本身是String或其超类型”(如ObjectSerializableCharSequence)。

最好的方式来理解Collection<? super String>是它不是Java中你所习惯的类型,而是一个用于匹配特定类型的模式

现在,你可以安全地向任何符合上述模式的集合中添加一个String或其子类(如果有)。这与你预期的完全相反,这就是泛型。


嘿,不错。为了完成你的示例,可以将一个String放入到Collection<? super CharSequence>中... - Lukas Eder
谢谢你清晰的解释,Marko。你的回答已经不是第一次帮助了我。 - Plain_Dude_Sleeping_Alone

3
使用Collection<? super String>,我们不知道它确切包含哪些对象,但我们知道它必须是一个StringString的某个超类的集合,即可以安全地将String放入其中,但不一定是Object。相反,对于从集合中取出东西的方法(例如迭代时),我们无法确定我们是否会得到字符串。
另一方面,使用Collection<? extends Foo>,我们知道它是一些东西的集合,这些东西是FooFoo的某个子类,因此我们可以安全地从集合中取出某些东西,并知道它将可分配给Foo,但我们无法放置任何东西,因为我们无法知道哪些类型是安全的。

很好的解释,我现在理解得更好了~ - Huibin Zhang

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接