Java泛型多态性

java Generics polymorphism

在下面的代码中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
        */



    }
}

我知道fe(List animals)方法不能通过List, List等。如果允许List方法,那么也可以添加animals.add(new Cat());方法,这是不可取的,因为运行时的类型擦除。所以只允许使用List

但是,我可以做以下操作

1
2
3
4
List<Animal> a = new ArrayList<Animal>();
        a.add(new Cat());
        a.add(new Dog());
and still call new AnimalFeeder().feed(a);

当我运行程序时,它给了我

1
2
3
Cat eating
Dog eating
Cat eating

我对多态通用概念的理解是"我们想要我们的List"。只接受List,而且该清单只包含动物,而不是猫或狗,换句话说只有动物"。不需要把狗或猫也包括在内吗?对吗?如果是,为什么允许我通过包含狗、猫等的List,这与通过(假设允许)List,然后将new Cat()添加到狗列表不一样吗?

我希望我的问题是清楚的。

我确实经历过list是list的子类吗?为什么Java泛型不是隐式多态的?

但我能找到我问题的答案吗?

谢谢,


My understanding of polymorphic generic concept is that"we want our List to accept only List

and also that that List contain only Animals, not Cat or Dog

不是真的

List可以包含Animal类的实例以及扩展Animal的任何类的实例。一个Dog和一个Cat都是Animal的,因此可以添加到List中。

另一方面,当您使用List类型时,您告诉编译器您的List应该只包含Dog个实例(或Dog子类的实例),所以这样的List不能包含Cats。


我们先不要把自己和仿制药混淆。考虑一下:

1
Animal cat = new Cat();

这是允许的,因为CatAnimal

换言之,类型为Animal的变量可以保存作为Animal或其子类的任何对象的引用。

回到泛型:

1
List<Animal> animals = new ArrayList<>();

animals是一个List类,可以容纳任何类型的Animal及其子类,与前面发生的情况类似。

一般情况和非一般情况的区别在于,一般情况只确保编译时的类型-在运行时清除该类型,因此List相当于运行时的List