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的超类)并且应该被允许? 显然不是!
有没有人有任何简单的例子?
你的直觉逻辑说“ List super Person>
是List super Person>
的一个列表或Person
的超类型 ,所以我自然可以添加一个Angel
”。 这种解释是错误的。
声明List super Person> list
List super Person> list
保证list
将是允许将任何Person
添加到列表中的类型。 由于Angel
不是Person
,编译器自然不允许这样做。 考虑使用insertElements(new ArrayList
调用您的方法。 将Angel
添加到这样的列表中是否可以? 当然不。
推理它的最好方法是List super Person>
List super Person>
不是明确的类型:它是描述允许作为参数的一系列类型的模式 。 看List
不是List super Person>
的子类型List super Person>
List super Person>
,但是匹配此模式的类型。 List super Person>
允许的操作 List super Person>
是任何匹配类型允许的那些。
对我来说,这些答案都不够明确,尽管他们帮助了我。 看了很多,我的意思是很多,我终于想出了通配符最简单的解释:
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 super Cat> 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
)。
传递具有特定类型元素的列表后,您只能向列表中添加 “Cat”或“Cat”子类型的元素,也就是说,它具有与所有元素集合一样的行为! 您无法将“ Animal ”添加到“ Cat ”列表中。 正如我之前所说的, 通配符不适用于元素本身,这些限制仅适用于“列表”。 现在为什么? 因为简单,明显,众所周知的原因:
动物动物=新狗();
如果您可以将 “动物” 添加到“猫”列表中,您还可以添加“狗”(狗是“动物”),但它不是“猫”。
反过来考虑一下:对于List super Person>
上绑定的类型List super Person>
List super Person>
, List
显然是参数的有效类型。 如果编译器允许您的代码,它将允许您将类型为Angel
插入List
。