Reputation: 31
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,
Upvotes: 2
Views: 158
Reputation: 8363
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.
Upvotes: 3
Reputation: 393781
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.
Upvotes: 8