Java泛型如何在泛型参数中接受任何派生类型 [英] Java generics How to accept any derived type in generic parameter
问题描述
在以下2行代码中
HashMap<Integer, ?extends Collection<String>> map=
new HashMap<Integer, TreeSet<String>>();
map.put(1,new TreeSet<String>());
第2行:方法put(整数,捕获#1-of?extends Collection)中的类型HashMap>不适用于参数(int,TreeSet)
Line 2 :The method put(Integer, capture#1-of ? extends Collection) in the type HashMap> is not applicable for the arguments (int, TreeSet)
第1行:这没有错误。
为什么第1行允许使用相同的泛型类型(TreeSet< String>)但第2行不允许?
Why is the same generic type (TreeSet< String >) allowed in Line 1 but not allowed in Line 2?
编辑:
使用super而不是extends ,为什么不允许以下内容。
Edit : With super instead of extends ,why is the following is NOT allowed.
HashMap<Integer, ?super Collection<String>> map=new HashMap(<Integer, TreeSet<String>>());
但是
HashMap<Integer, ?super Collection<String>> map=new HashMap();
map.put(1,new TreeSet<String>());
允许
推荐答案
您收到编译器错误的原因与您无法将 Dog
添加到列表<? extends Animal>
- 当引用变量的类型具有上限通配符时,不能使用泛型参数调用方法。 map
变量的值类型参数可以引用与匹配的任何类型? extends Collection< String>
,可能是 HashMap< Integer,LinkedList< String>>
。您可以在调用 put
之前合法插入此行:
The reason you get a compiler error is the same reason you cannot add a Dog
to a List<? extends Animal>
-- you cannot call a method with a generic parameter when the type of the reference variable has an upper bound wildcard. The map
variable's value type parameter could refer to any type that matches ? extends Collection<String>
, perhaps as HashMap<Integer, LinkedList<String>>
. You could legally insert this line before the call to put
:
map = new HashMap<Integer, LinkedList<String>>();
编译器不知道地图中确切的类型,所以它必须在编译时时间,阻止你把
TreeSet< String>
作为一个值输入到一个值可能是某个地图的地图上例如 LinkedList< String>
。
The compiler doesn't know the exact type that's really in the map, so it must, at compile time, prevent you from put
ting a TreeSet<String>
in as a value to a map whose value could be something like LinkedList<String>
.
到 put
a map
中的值(除了 null
),您必须删除通配符。
To put
a value in map
(besides null
), you must remove the wildcard.
HashMap<Integer, TreeSet<String>> map =
new HashMap<Integer, TreeSet<String>>();
正如JB Nizet发表评论的那样,您仍然可以设置任何集合的值
,例如 TreeSet
如果删除通配符但保留 Collection
。
As JB Nizet has commented, you still can put a value of any Collection
such as TreeSet
if you remove the wildcard but keep Collection
.
HashMap<Integer, Collection<String>> map =
new HashMap<Integer, Collection<String>>();
(另外,钻石运营商可以在这里简化声明。)
(Also, the diamond operator can simplify the declarations here.)
在这里,您使用了下限。
Here, you've used a lower bound.
HashMap<Integer, ? super Collection<String>> map = new HashMap<Integer, TreeSet<String>>());
类型参数可能是集合< String>
或任何超类型,例如 Object
。这不允许使用 TreeSet< String>
等子类型。 Java的泛型是不变的。允许从 Collection< String>
进行任何变更的唯一原因是因为通配符。
The type parameter may be Collection<String>
or any supertype, such as Object
. This disallows subtypes such as TreeSet<String>
. Java's generics are invariant. The only reason any variation from Collection<String>
is allowed is because of the wildcard.
HashMap<Integer, ? super Collection<String>> map = new HashMap<>();
map.put(1, new TreeSet<String>());
这是允许的,因为任何超类型 Collection< String>
将匹配任何子类型作为参数。毕竟, TreeSet< String>
是一个对象
。 TreeSet< String>
可以 put
作为 map $ c $的值c>,是否是
HashMap< Integer,Object>
或 HashMap< Integer,Collection< String>>
,或其间的任何类型。编译器可以证明类型安全,因此允许调用。
This is allowed because any supertype of Collection<String>
will match any subtype as an argument. After all, a TreeSet<String>
is an Object
. A TreeSet<String>
can be put
as a value to map
, whether it's a HashMap<Integer, Object>
or a HashMap<Integer, Collection<String>>
, or any type in between. The compiler can prove type safety, so it allows the call.
这篇关于Java泛型如何在泛型参数中接受任何派生类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!