这不是一个重复的问题,因为我特别询问编译器如何允许将Cat添加到ALREADY包含Dog的List<? super Cat> catList
集合。您看到animaList已经包含Cats and Dogs,因为它们是动物但是调用使用List<? super Cat>
的addCat允许添加新的Cat即add(new RedCat());
,尽管该列表已包含Dog。编译器是否不允许这样做才能满足List<? super Cat>
签名,因为它试图将Cats添加到已经包含Dogs的列表中?
然而明确地调用
catList.add(new Dog());
强制执行约束。所以问题是为什么行为的差异?
原始问题:
我一直在玩Java泛型并注意到一个奇怪的(?)问题。
在下面的代码片段中,您可以将Dog和Cat添加到animalList中,然后将此列表传递到addCat(List<? super Cat> catList)
并添加另一个Cat实例。所以我们有一个包含狗和猫的列表覆盖了?超级猫的边界,因为它不应该允许狗?
但是,只要取消注释
即可//catList.add(new Dog());
行,你得到一个编译时错误
进行了修订(参数不匹配; Dog无法转换为CAP#1)
package com.tutorialspoint;
import java.util.ArrayList;
import java.util.List;
public class GenericsTester {
public static void addCat(List<? super Cat> catList) {
catList.add(new RedCat());
catList.add(new Cat());
//catList.add(new Dog());
System.out.println("Cat Added");
}
public static void main(String[] args) {
List<Animal> animalList= new ArrayList<Animal>();
List<Cat> catList= new ArrayList<Cat>();
List<RedCat> redCatList= new ArrayList<RedCat>();
List<Dog> dogList= new ArrayList<Dog>();
animalList.add(new Dog());
animalList.add(new Cat());
animalList.add(new RedCat());
addCat(animalList);
System.out.println("all ok");
}
}
class Animal {}
class Cat extends Animal {}
class RedCat extends Cat {}
class Dog extends Animal {}
答案 0 :(得分:5)
List<? super Cat>
可以是List<Cat>
,List<Animal>
或List<Object>
。您的方法应该适用于任何这些可能性。
由于您无法将Dog
添加到List<Cat>
,因此无法将其添加到List<? super Cat>
。
答案 1 :(得分:1)
您应该阅读PECS(Producer Extends Consumer Super)以及为什么该规则就是这样。它还解释了为什么Java集合本质上是不变的,以及允许哪种类型的赋值。
鉴于你的集合采用任何超类Cat并且它是一个可以消耗的集合定义,它只能使用Cat,Animal或Object