6

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

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

4 回答 4

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

您不能将 a List(的返回类型Collections.singletonList()放入 a Mapof,? extends List因为实际类型可以是 的任何实现List。例如,将泛型放入 a是不安全的,因为a可能不是 a 。但是,我们可以轻松地将一个变成一个。ListMap<String,LinkedList>ListLinkedListLinkedListMap<String,List>

我认为你在考虑你的泛型。您不必使用? extends非泛型类。例如,List<Object>将持有 any Object? extends不需要添加对象。AList<List<Foo>>只会接受List<Foo>对象而不接受List<FooSubclass>对象[泛型类不会根据它们的参数继承]。这就是? extends发挥作用的地方。要将List<Foo>和都添加List<FooSubclass>到 aList中,类型必须是List<List<? extends Foo>>

于 2009-05-16T02:52:23.727 回答
6

行不通Map<String, List<String>?有什么特别的原因你必须在那里有一个通配符吗?

于 2009-05-16T02:53:08.763 回答
4

将集合和泛型一起使用时,有一个非常简单的原则。它被称为“获取和放置原则”:

当你只从集合中获取值时使用“扩展”通配符,当你只将值放入集合时使用“超级”通配符,当你想要获取和放置时不要使用任何通配符。

所以,如你所见,根据这个原则,最初的例子是无效的。

于 2009-10-06T09:44:49.290 回答
0

想象一下,如果有人给你一个Map<String, ArrayList<String>>. 您输入的值是 Collections.singletonList 的结果,它不是ArrayList.

您不能在 Map 中接受 List 的任何子类型,然后期望能够添加您自己的,可能不兼容的子类型。

于 2009-05-16T03:43:10.360 回答