[英]Java Generics putting on Map<String, ? extends List<String>>
Is there a way to make the following implementation in a type safe manner? 有没有办法以类型安全的方式进行以下实现?
public void myMethod( Map<String, ? extends List<String>> map )
{
map.put("foo", Collections.singletonList("bar");
}
The above implementation doesn't work. 上述实现不起作用。 It requires a
Map<String, ? super List<String>>
它需要
Map<String, ? super List<String>>
Map<String, ? super List<String>>
to compile the method map.put()
correctly. Map<String, ? super List<String>>
正确编译方法map.put()
。 But myMethod won't accept any subtype of List this way. 但myMethod不会以这种方式接受List的任何子类型。 So, I have to use
Map<String, ? extends List<String>>
所以,我必须使用
Map<String, ? extends List<String>>
Map<String, ? extends List<String>>
instead. Map<String, ? extends List<String>>
。 How can I solve this problem in a type safe manner? 如何以类型安全的方式解决此问题?
public void myMethod( Map<String, List<String>> map ) {
map.put("foo", Collections.singletonList("bar") );
}
You can't put a List
(the return type of Collections.singletonList()
into a Map
of ? extends List
since the actual type could be any implementation of List
. For example, it is not safe to put a generic List
into a Map<String,LinkedList>
since the List
might not be a LinkedList
. However, we can easily put a LinkedList
into a Map
of <String,List>
. 你不能把一个
List
(返回类型的Collections.singletonList()
到Map
的? extends List
,因为实际的类型可能是任何实现List
。例如,它是不是安全的把一个普通的List
到Map<String,LinkedList>
因为List
可能不是LinkedList
。但是,我们可以轻松地将LinkedList
放入<String,List>
的Map
中。
I think you were over thinking your generics. 我想你已经在考虑你的仿制药了。 You do not have to use
? extends
你不必使用
? extends
? extends
for a non-generic class. ? extends
为非泛型类。 For example, List<Object>
will hold any Object
, the ? extends
例如,
List<Object>
将持有的任何Object
,则? extends
? extends
is not needed to add an object. 不需要
? extends
来添加对象。 A List<List<Foo>>
will only take List<Foo>
objects and not List<FooSubclass>
objects [Generic classes don't inherit based on their parameters]. List<List<Foo>>
只接受List<Foo>
对象而不是List<FooSubclass>
对象[通用类不会根据它们的参数继承]。 This is where ? extends
这是哪里
? extends
? extends
comes into play. ? extends
发挥作用。 To add both List<Foo>
and List<FooSubclass>
to a List
, the type must be List<List<? extends Foo>>
要将
List<Foo>
和List<FooSubclass>
到List
,类型必须是List<List<? extends Foo>>
List<List<? extends Foo>>
. List<List<? extends Foo>>
。
Wouldn't Map<String, List<String>
work? Map<String, List<String>
不会工作吗? Is there some particular reason you have to have a wildcard there at all? 有什么特别的原因你必须在那里有一个通配符吗?
There is a very simple principle when using Collections and Generics together. 将Collections和Generics一起使用时,有一个非常简单的原则。 It is called "The Get and The Put Principle":
它被称为“获取和放置原则”:
Use an "extends" wildcard when you only GET values out of a collection, use "super" wildcard when you only PUT values into a collection and don't use any wildcard when you want both get and put. 当你只从集合中获取值时使用“扩展”通配符,当你只将PUT值放入集合时使用“超级”通配符,当你想要get和put时不使用任何通配符。
So, as you can see, the initial example is invalid, according to this principle. 所以,正如你所看到的,根据这个原则,最初的例子是无效的。
Imagine if someone passed you a Map<String, ArrayList<String>>
. 想象一下,如果有人传给你一个
Map<String, ArrayList<String>>
。 The value you're putting in is the result of Collections.singletonList which is not an ArrayList
. 您输入的值是Collections.singletonList的结果,它不是
ArrayList
。
You cannot accept any subtype of List in the Map and then expect to be able to add your own, possibly incompatible, subtype. 您不能接受Map中任何List的子类型,然后期望能够添加您自己的,可能不兼容的子类型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.