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();

这是允许的,因为Cat是Animal。

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

回到泛型:

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

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

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