泛型 - 集合中的Java集合

cla*_*ire 9 java generics collections nested

我是仿制药的新手,所以不确定我哪里出错了......

我有一个名为Cat,Dog和Rabbit的类,它们实现了Animal的接口.

以下代码将编译

Set<? extends Animal> animalSet;
Set<Dog> dogSet = new HashSet<Dog>();
animalSet = dogSet;
Run Code Online (Sandbox Code Playgroud)

但是下面的代码不会

Map<String, Set<? extends Animal>> animalMap;
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();
animalMap = dogMap; // this line will not compile
Run Code Online (Sandbox Code Playgroud)

编译器说这些类型是不兼容的.我哪里错了?

UPDATE

谢谢大家的帮助

我通过添加另一个通配符更改了第一行代码以下代码将编译

Map<String, ? extends Set<? extends Animal>> animalMap;
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();
animalMap = dogMap;
Run Code Online (Sandbox Code Playgroud)

另请参阅下面的Cyrille Ka给出的解决方案 - 使用putAll()将值从dogMap传输到animalMap,而不是将dogMap分配给animalMap.

Cyr*_* Ka 7

基本上,当你写:

Map<String, Set<? extends Animal>> animalMap;
Run Code Online (Sandbox Code Playgroud)

您声明地图的任何值都是一个集合,可以包含任何类型为Animal子类的对象.那么客户端代码编写是完全合理的:

animalMap.put("miaow", aCatSet);
Run Code Online (Sandbox Code Playgroud)

这里acatSet是一个Set<Cat>.

dogMap不能接受一个Set<Cat>值,它只能接受Set<Dog>.因此,存在类型不兼容的可能性,这就是禁止这种结构的原因.

编辑:至于如何解决这个问题,这取决于你想做什么.如果你有dogMap某个地方想要将其内容放入其中,animalMap那么你可以简单地复制这样的内容:

Map<String, Set<? extends Animal>> animalMap = new HashMap<String, Set<? extends Animal>>();
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();

/// fill dogMap

animalMap.putAll(dogMap);
Run Code Online (Sandbox Code Playgroud)


小智 2

您的问题的解决方案是这样的:

Map<String, ? extends Set<? extends Animal>> animalMap;
Map<String, Set<Dog>> dogMap = new HashMap<String, Set<Dog>>();
animalMap = dogMap;
Run Code Online (Sandbox Code Playgroud)

因为Set<Dog>不是 a Set<? extends Animal>,而是它的扩展。