Java Generics put on Map <string,?=“”extends =“”list <string =“”>&gt; </string,>

时间:2009-05-16 02:17:35

标签: java generics list collections map

有没有办法以类型安全的方式进行以下实现?

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>>代替。如何以类型安全的方式解决此问题?

4 个答案:

答案 0 :(得分:20)

public void myMethod( Map<String, List<String>> map ) {
    map.put("foo", Collections.singletonList("bar") );
}

您不能将ListCollections.singletonList()的返回类型放入Map ? extends List,因为实际类型可能是List的任何实现例如,将通用List放入Map<String,LinkedList>安全的,因为List可能不是LinkedList。 ,我们可以轻松地将LinkedList加入Map <String,List>

我认为你在想你的仿制品。您不必将? extends用于非泛型类。例如,List<Object>将保留任何Object,添加对象不需要? extendsList<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的子类型,然后希望能够添加您自己的,可能不兼容的子类型。