Alex Rivera | Logout

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

Asked 2010-04-30T14:39:39.237
922

I'm a bit confused about how Java generics handle inheritance / polymorphism.

Assume the following hierarchy -

Animal (Parent)

Dog - Cat (Children)

So suppose I have a method doSomething(List<Animal> animals). By all the rules of inheritance and polymorphism, I would assume that a List<Dog> is a List<Animal> and a List<Cat> is a List<Animal> - and so either one could be passed to this method. Not so. If I want to achieve this behavior, I have to explicitly tell the method to accept a list of any subclass of Animal by saying doSomething(List<? extends Animal> animals).

I understand that this is Java's behavior. My question is why? Why is polymorphism generally implicit, but when it comes to generics it must be specified?

Edit
Report

1 Answer

113

What you are looking for is called covariant type parameters. This means that if one type of object can be substituted for another in a method (for instance, Animal can be replaced with Dog), the same applies to expressions using those objects (so List<Animal> could be replaced with List<Dog>). The problem is that covariance is not safe for mutable lists in general. Suppose you have a List<Dog>, and it is being used as a List<Animal>. What happens when you try to add a Cat to this List<Animal> which is really a List<Dog>? Automatically allowing type parameters to be covariant breaks the type system.

It would be useful to add syntax to allow type parameters to be specified as covariant, which avoids the ? extends Foo in method declarations, but that does add additional complexity.

answered 2010-04-30T14:44:47.857

Your Answer