Java泛型:将Map<String,?extends List<String>>放入

6
有没有一种类型安全的方法来实现以下内容?
public void myMethod( Map<String, ? extends List<String>> map )
{
   map.put("foo", Collections.singletonList("bar");
}

上述实现是无法工作的。它需要一个Map<String, ? super List<String>>才能正确编译方法map.put()。但是我的方法不会以这种方式接受List的任何子类型。因此,我必须使用Map<String, ? extends List<String>>。如何以类型安全的方式解决这个问题?

4个回答

20
public void myMethod( Map<String, List<String>> map ) {
    map.put("foo", Collections.singletonList("bar") );
}
无法将Collections.singletonList()方法的返回类型List放入一个? extends ListMap中,因为实际类型可能是List的任何实现。例如,将通用的List放入Map<String,LinkedList>不安全,因为List可能不是LinkedList。但是,我们可以轻松地将LinkedList放入<String,List>Map中。
我认为你过于复杂化了泛型。对于非泛型类,您无需使用? extends。例如,List<Object> 可以容纳任何Object,不需要使用? extends添加对象。 List<List<Foo>>将仅接受List<Foo>,而不接受List<FooSubclass> [泛型类不基于其参数进行继承]。这就是? extends派上用场的地方。要将List<Foo>List<FooSubclass>都添加到List中,类型必须为List<List<? extends Foo>>

2
+1 个好的解释(现在你的泛型是可见的 :P)。 - Michael Myers
哎呀。我一直以为因为SOF过滤文本,所以它会修复尖括号的问题。唉... - KitsuneYMG

6
< p> Map<String,List<String> 不行吗?您是否有任何特殊原因必须在那里使用通配符?


4
当使用集合和泛型时,有一个非常简单的原则,称为“获取和放置原则”:
当您只从集合中获取值时,请使用“extends”通配符;当您只将值放入集合中时,请使用“super”通配符;如果您既需要获取也需要放置,则不要使用任何通配符。
因此,根据这个原则,可以看出,初始示例是无效的。

0
想象一下,如果有人给你传递了一个Map<String, ArrayList<String>>。你要放入的值是由Collections.singletonList生成的,它不是一个ArrayList
在Map中,你不能接受List的任何子类型,然后期望能够添加自己的、可能不兼容的子类型。

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