简体   繁体   English

java泛型多态性

[英]java Generics polymorphism

In code below 在下面的代码中

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
        */


    }
}

I understand that feed (List<Animal> animals) method cannot be passed a List<Dog>, List<Cat> etc. If List<Dog> were allowed, then animals.add(new Cat()); 我知道feed (List<Animal> animals)方法不能传递List<Dog>, List<Cat>等。如果允许List<Dog> ,那么animals.add(new Cat()); can be added too which is not desirable and because of type erasure at runtime. 也可以添加,这是不可取的,因为在运行时类型擦除。 So only List<Animal> is allowed. 所以只允许List<Animal>

However, I can do the following 但是,我可以做到以下几点

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

and when I run the program, it gives me 当我运行程序时,它给了我

Cat eating
Dog eating
Cat eating

My understanding of polymorphic generic concept is that "we want our List<Animal> to accept only List<Animal> and also that that List contain only Animals, not Cat or Dog, in other words only Animals". 我对多态通用概念的理解是“我们希望List<Animal>只接受List<Animal> ,而且List只包含List<Animal> ,而不是Cat或Dog,换句话说只包含List<Animal> ”。 Any other inclusion of dog or Cat is not wanted? 不想要任何其他包含狗或猫的东西吗? Is that right? 那正确吗? If yes, why am I allowed to pass List<Animal> that contain dogs, cats etc. Is this not same thing as passing (assuming it is allowed) List<Dog> and then adding new Cat() to dog list? 如果是的话,为什么我允许传递包含狗,猫等的List<Animal> 。这与传递(假设允许)不一样List<Dog>然后将new Cat()添加到狗列表中?

I hope my question is clear. 我希望我的问题很清楚。

I did go through Is List<Dog> a subclass of List<Animal>? 我确实通过了List List <Dog>是List <Animal>的子类吗? Why are Java generics not implicitly polymorphic? 为什么Java泛型不是隐式多态的?

but I could find the answer to my question? 但我能找到问题的答案吗?

thanks, 谢谢,

My understanding of polymorphic generic concept is that "we want our List to accept only List 我对多态通用概念的理解是“我们希望我们的List只接受List

true 真正

and also that that List contain only Animals, not Cat or Dog 并且该列表仅包含动物,而不包含猫或狗

not true 不对

A List<Animal> can contain instances of the Animal class as well as instances of any class that extends Animal . List<Animal>可以包含Animal类的实例以及扩展Animal的任何类的实例。 A Dog and a Cat are both Animal s, so they can be added to a List<Animal> . DogCat都是Animal ,因此可以将它们添加到List<Animal>

On the other hand, when you use the type List<Dog> , you are telling the compiler your List should only contains Dog instances (or instances of sub-classes of Dog ), so such a List cannot contain Cat s. 在另一方面,当您使用类型List<Dog> ,你告诉编译器的List应该只包含Dog实例(或子类的实例Dog ),所以这样的List不能包含Cat秒。

Let's not confuse yourself with generics first. 我们不要先将自己与泛型混淆。 Consider this: 考虑一下:

Animal cat = new Cat();

This is allowed because a Cat is an Animal . 这是允许的,因为CatAnimal

In other words, a variable of type Animal can hold the reference of any object that is an Animal or its subclass. 换句话说, Animal类型的变量可以保存作为Animal或其子类的任何对象的引用。

Back to generics: 回到泛型:

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

animals is a List that can hold any kind of Animal and its subclass , similar to what happened earlier. animals是一个List ,可以容纳任何种类的Animal 及其子类 ,类似于之前发生的事情。

The difference between generic and non-generic cases is that generic only ensure type at compile-time - the type is erased at runtime so List<Animal> is equivalent to List<Object> at runtime. 泛型和非泛型情况之间的区别在于,通用仅在编译时确保类型 - 类型在运行时被擦除,因此List<Animal>在运行时等效于List<Object>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM