简体   繁体   中英

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()); can be added too which is not desirable and because of type erasure at runtime. So only List<Animal> is allowed.

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". 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?

I hope my question is clear.

I did go through Is List<Dog> a subclass of List<Animal>? Why are Java generics not implicitly polymorphic?

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

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 . A Dog and a Cat are both Animal s, so they can be added to a 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.

Let's not confuse yourself with generics first. Consider this:

Animal cat = new Cat();

This is allowed because a Cat is an Animal .

In other words, a variable of type Animal can hold the reference of any object that is an Animal or its subclass.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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