1

Some days ago I was writing a simple Java program, and I discovered that this piece of code doesn't work (it gives a compile-time error):

ArrayList<Document> docs = new ArrayList<Book>();

where Document is an interface and Book implements Document.

Why inheritance in Java doesn't work with generics? If I want that code to work, I must use wildcards, like this:

ArrayList<? extends Document> docs = new ArrayList<Book>();

I was wondering what is the reason of this? If I need an ArrayList of Documents, and I know that a Book is also a Document, why can't I use an ArrayList of Books as an ArrayList of Documents?

user2302436
  • 518
  • 2
  • 9
  • http://stackoverflow.com/questions/10770585/why-polymorphism-doesnt-treat-generic-collections-and-plain-arrays-the-same-way – Davey Chu Jun 16 '13 at 09:03
  • 1
    Once you've combed through the answers as to why your first statement doesn't work, see [my answer to this question](http://stackoverflow.com/a/12605337/646634) for an explanation of `extends` and `super` and what they do. – Brian Jun 16 '13 at 09:28

2 Answers2

7

consider the following example:

ArrayList<Book>books = new ArrayList<Book>();
ArrayList<Document> docs = new ArrayList<Book>();
docs.add(new Document());
Book book = books.get(0); //Oops, now we have a variable of type book, referring to a Document that is not a book. Not good.

If you want more conceptual background material about this issue read up on Covariance and Contravariance

Jens Schauder
  • 77,657
  • 34
  • 181
  • 348
5

It's just because the type of List<U> can't be a type a subtype of List<V> (unless U = V).

enter image description here

If you admit for example that List<Integer> is a subtype of List<Number>. You could write the following :

void addPi(List<Number> l) {
 l.add(3.14);
}

List<Integer> l = new LinkedList<>();
addPi(l);

What is the problem here ?

Alexis C.
  • 91,686
  • 21
  • 171
  • 177