我可以使用基本的通用表达式,但是通配符约束只是让我心烦意乱.
信息:学生扩展人和人扩展动物
List<? super Animal> aList= new ArrayList<>();
// does not compile as expected,
// since the list is restricted to something that has Animal as superclass.
// aList.add(new Object());
aList.add(new Animal()); // I can add animal
aList.add(new Person()); // I can add Person
aList.add(new Student()); // I can add Student
Animal a = new Animal();
Animal b = new Animal();
Person p = new Person();
Student s = new Student();
// test
a = b; //I can assign an animal to another animal
a = p; // I can assign a person to an animal
a = s; // I can assign a student to an animal
Animal animal = aList.get(0); // DOES NOT COMPILE, WHY ?
Run Code Online (Sandbox Code Playgroud)
问题:我不明白为什么最后一项任务不起作用.上面的例子显示,该列表中的任何内容肯定是动物,但我无法从该列表中获取动物.
更具体:当我知道我只能添加Animal作为超类的类型时,为什么我不能期望从Animal类型中删除对象?
事实:我只能添加扩展Animal的对象!我只是试图添加一个汽车对象,它不起作用!
我开始怀疑我的理智,我希望你能帮助我.谢谢
另外:
Object animal = aList.get(0); // works
Run Code Online (Sandbox Code Playgroud)
为什么即使我知道无法添加对象类型,此语句仍然有效?
解决方案:(根据接受的答案)
我误解了意思 <? super Animal>
我认为这意味着:任何具有Animal作为超类的类.
它(显然)意味着什么:任何一类是动物的超类.
因此,List也可能包含Object类型的对象,这就是Animal animal = aList.get(0);失败的原因.
干杯
Bri*_*etz 15
这里的其他答案是正确的,但没有明确说明,这是混乱的来源.
一个List<? extends Animal>不会不意味着"的东西,都可以扩展动物名单".它的意思是"某种类型的列表T,我不会告诉你它是什么,但我知道它会T扩展Animal." (在类型理论中,这些被称为存在类型 - 存在一种T我们List是a 的类型List<T>,但我们不一定知道它是什么T.)
差异很重要.如果你有"所有扩展的东西列表Animal",那么将一条狗添加到列表中是安全的 - 但这不是通配符所表达的.A List<? extends Animal>表示"某物的列表,其中某物延伸到动物".它可能是a List<Animal>,或a List<Dog>,或List<Cat>- 我们不知道.因此,我们没有理由认为将狗添加到该列表是安全的 - 因为也许我的列表是一个List<Cat>.
在你的例子中,你有一个List<? super Animal>.这意味着,某些类型T的列表,其中T是Animal的超类型之一.它可能是a List<Object>,或者List<Animal>,或者如果Animal有一个超类型HasLegs,它可能是一个List<HasLegs>.在这里,将 Dog放入此列表是安全的- 因为无论它的列表是什么,Dog绝对是其中之一(Animal,Object等),但当你从列表中取出一些东西时,你不知道它是否是狗,动物,或只是一个对象.
Psh*_*emo 10
List<? super Animal> aList其可以被用来处理是参考List<Animal> ,它也可以是动物的任何超类如List<Object>.
换句话说List<? super Animal> aList
- 不是引用一些可以存储任何超类型Animal的列表.
+它是某些特定类型的列表的引用,它是Animal(包括Animal本身)的超类型但你不知道它究竟是哪种类型.
所以它可能是
List<Object> someList = new ArrayList<>();
someList.add(new Car());//OK since Car is a Object
List<? super Animal> aList = someList;// OK since Object is supertype of Animal
Run Code Online (Sandbox Code Playgroud)
因此,代码
Animal a = aList.get(0);//and where did that Car come from?
Run Code Online (Sandbox Code Playgroud)
不安全 只有安全型存储的结果get(0)是Object让你无论是需要
Object o = aList.get(0);
Run Code Online (Sandbox Code Playgroud)
或者如果您想确保get将返回Animal,请更改您的aList引用类型List<Animal>甚至List<? extends Animal>.