Java泛型如何在泛型参数中接受任何派生类型 [英] Java generics How to accept any derived type in generic parameter

查看:175
本文介绍了Java泛型如何在泛型参数中接受任何派生类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在以下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 putting 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 ,是否是 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆