有没有办法以类型安全的方式进行以下实现?
public void myMethod( Map<String, ? extends List<String>> map )
{
map.put("foo", Collections.singletonList("bar");
}
以上实施不起作用。它需要Map<String, ? super List<String>>
才能正确编译方法map.put()
。但myMethod不会以这种方式接受List的任何子类型。所以,我必须使用Map<String, ? extends List<String>>
代替。如何以类型安全的方式解决此问题?
答案 0 :(得分:20)
public void myMethod( Map<String, List<String>> map ) {
map.put("foo", Collections.singletonList("bar") );
}
您不能将List
(Collections.singletonList()
的返回类型放入Map
? extends List
,因为实际类型可能是List
的任何实现例如,将通用List
放入Map<String,LinkedList>
是不安全的,因为List
可能不是LinkedList
。 ,我们可以轻松地将LinkedList
加入Map
<String,List>
。
我认为你在想你的仿制品。您不必将? extends
用于非泛型类。例如,List<Object>
将保留任何Object
,添加对象不需要? extends
。 List<List<Foo>>
只会占用List<Foo>
个对象,而不会占用List<FooSubclass>
个对象[通用类不会根据其参数继承]。这是? extends
发挥作用的地方。要将List<Foo>
和List<FooSubclass>
添加到List
,类型必须为List<List<? extends Foo>>
。
答案 1 :(得分:6)
Map<String, List<String>
不会有效吗?有什么特别的原因你必须在那里有一个通配符吗?
答案 2 :(得分:4)
将Collections和Generics一起使用时,有一个非常简单的原则。它被称为“获取和放置原则”:
当你只从集合中获取值时使用“extends”通配符,当你只将PUT值放入集合时使用“super”通配符,当你想要get和put时不使用任何通配符。
所以,正如你所看到的,根据这个原则,最初的例子是无效的。
答案 3 :(得分:0)
想象一下,如果有人通过你Map<String, ArrayList<String>>
。你输入的值是Collections.singletonList的结果,不是 ArrayList
。
您不能接受Map中任何List的子类型,然后希望能够添加您自己的,可能不兼容的子类型。