Java下界通配符

我正在努力解决这个问题,并且想知道是否有人可以解释原因

我有3个class级员工,人,天使

员工延伸人和人延伸天使

当我尝试执行此代码时:

public static void insertElements(List list){ list.add(new Person("Mike", 42)); list.add(new Employee()); list.add(new Angel()); } 

我收到一个错误

类型List中的方法add(捕获#5-of?super Person)不适用于参数(Angel)

我一直在阅读文档意味着任何类型的X或X的超类(所以在我的情况下,Angel是Person的超类)并且应该被允许? 显然不是!

有没有人有任何简单的例子?

你的直觉逻辑说“ ListList的一个列表或Person的超类型 ,所以我自然可以添加一个Angel ”。 这种解释是错误的。

声明List list List list保证list将是允许将任何Person添加到列表中的类型。 由于Angel 不是Person ,编译器自然不允许这样做。 考虑使用insertElements(new ArrayList)调用您的方法。 将Angel添加到这样的列表中是否可以? 当然不。

推理它的最好方法是List List不是明确的类型:它是描述允许作为参数的一系列类型的模式 。 看List不是List的子类型List List ,但是匹配此模式的类型。 List允许的操作 List是任何匹配类型允许的那些。

对我来说,这些答案都不够明确,尽管他们帮助了我。 看了很多,我的意思是很多,我终于想出了通配符最简单的解释:

 public class CatTest { public class Animal {} public class Cat extends Animal {} public class MyCat extends Cat {} public class Dog extends Animal {} public void addMethod(List catList) { catList.add(new MyCat()); System.out.println("Cat Added"); } public static void main(String[] args) { List animalList= new ArrayList(); List catList= new ArrayList(); List myCatList= new ArrayList(); List dogList= new ArrayList(); CatTest catTest= new CatTest(); // Here you are trying to add a MyCat instance(in the addMethod we create a MyCat instance). MyCat is a Cat, Cat is an Animal, therefore MyCat is an Animal. // So you can add a new MyCat() to a list of List because it's a list of Animals and MyCat IS an Animal. catTest.addMethod(animalList); // Here you are trying to add a MyCat instance(in the addMethod we create a MyCat instance). MyCat is a Cat. // So you can add a new MyCat() to a list of List because it is a list of Cats, and MyCat IS a Cat catTest.addMethod(catList); // ***Here are trying to add a MyCat instance(in the addMethod we create a MyCat instance). MyCat is a Cat. // Everything should work but !!! THE PROBLEM HERE is that you restricted(bounded) the type of the lists to be passed to the method to be of // a type that is either "Cat" or supertype of "Cat". While "MyCat" IS a "Cat". It IS NOT a supertype of "Cat". Therefore you cannot use the method catTest.addMethod(myCatList); // DOESN'T COMPILE // Here you are adding a MyCat instance(in the addMethod we create a MyCat instance). MyCat is a Cat. // You CANNOT call the method here, because "Dog" is not a "Cat" or a supertype of "Cat" catTest.addMethod(dogList); // DOESN'T COMPILE } 

}

最后,这些是结论:

通配符 适用于作为方法参数传递的列表类型而不是当您尝试将元素添加到列表时, 不适用于 元素 的类型 。 因此,您只能传递 “Cat”元素列表或“Cat”类型的超级元素List, List 。( List, List )。

传递具有特定类型元素的列表后,您只能向列表中添加 “Cat”或“Cat”子类型的元素,也就是说,它具有与所有元素集合一样的行为! 您无法将“ Animal ”添加到“ Cat ”列表中。 正如我之前所说的, 通配符不适用于元素本身,这些限制仅适用于“列表”。 现在为什么? 因为简单,明显,众所周知的原因:

动物动物=新狗();

如果您可以将 “动物” 添加到“猫”列表中,您还可以添加“狗”(狗是“动物”),但它不是“猫”。

反过来考虑一下:对于List上绑定的类型List ListList显然是参数的有效类型。 如果编译器允许您的代码,它将允许您将类型为Angel插入List