在下面的代码中
public class Animal {
public void eat() {
System.out.println("Animal eating");
}
}
public class Cat extends Animal {
public void eat() {
System.out.println("Cat eating");
}
}
public class Dog extends Animal {
public void eat() {
System.out.println("Dog eating");
}
}
public class AnimalFeeder {
public void feed(List<Animal> animals) {
animals.add(new Cat());
animals.forEach(animal -> {
animal.eat();
});
}
public static void main(String args[]){
List<Animal> a = new ArrayList<Animal>();
a.add(new Cat());
a.add(new Dog());
new AnimalFeeder().feed(a);
/* List<Dog> dogs = new ArrayList<>();
dogs.add(new Dog());
dogs.add(new Dog());
new AnimalFeeder().feed(dogs); // not allowed
*/
}
}
我知道feed (List<Animal> animals)
方法不能传递 List<Dog>, List<Cat>
等 . 如果允许 List<Dog>
,那么也可以添加 animals.add(new Cat());
,这是不可取的,因为在运行时类型擦除 . 所以只允许 List<Animal>
.
但是,我可以做到以下几点
List<Animal> a = new ArrayList<Animal>();
a.add(new Cat());
a.add(new Dog());
and still call new AnimalFeeder().feed(a);
当我运行程序时,它给了我
Cat eating
Dog eating
Cat eating
我对多态通用概念的理解是“我们希望我们的 List<Animal>
只接受 List<Animal>
,并且该列表仅包含动物,而不包含猫或狗,换句话说只包含动物” . 不想要任何其他包含狗或猫的东西吗?是对的吗?如果是的话,为什么我允许传递包含狗,猫等的 List<Animal>
. 这与传递(假设允许) List<Dog>
然后将 new Cat()
添加到狗列表不一样吗?
我希望我的问题很明确 .
我确实经历了Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?
但我能找到问题的答案吗?
谢谢,
2 回答
真正
不对
List<Animal>
可以包含Animal
类的实例以及扩展Animal
的任何类的实例 .Dog
和Cat
都是Animal
s,因此它们可以添加到List<Animal>
.另一方面,当您使用类型
List<Dog>
时,您告诉编译器您的List
应该只包含Dog
实例(或Dog
的子类实例),因此这样的List
不能包含Cat
.我们不要先将自己与泛型混淆 . 考虑一下:
这是允许的,因为
Cat
是Animal
.换句话说,
Animal
类型的变量可以保存任何对象的引用,该对象是Animal
或其子类 .回到泛型:
animals
是List
,可以容纳任何类型的Animal
及其子类,类似于之前发生的情况 .泛型和非泛型情况之间的区别在于,通用仅在编译时确保类型 - 类型在运行时被擦除,因此
List<Animal>
在运行时等效于List<Object>
.