tags:

views:

70

answers:

3
+1  Q: 

Generics in Java

+2  A: 

This is a common source of confusion - generics are not covariant in Java.

For a really good explanation of this please see Java theory and practice: Generics gotchas:

While you might find it helpful to think of collections as being an abstraction of arrays, they have some special properties that collections do not. Arrays in the Java language are covariant -- which means that if Integer extends Number (which it does), then not only is an Integer also a Number, but an Integer[] is also a Number[], and you are free to pass or assign an Integer[] where a Number[] is called for. (More formally, if Number is a supertype of Integer, then Number[] is a supertype of Integer[].) You might think the same is true of generic types as well -- that List is a supertype of List, and that you can pass a List where a List is expected. Unfortunately, it doesn't work that way.

Andrew Hare
+3  A: 

You need to use wild card. Like this:

List<Rectangle> test1 = new LinkedList<Rectangle>();
List<? extends Shape> test2 = test1;

As Rectangle extends Shape.

The reason for this is that if test2 is just List<Shape>, you will expect test2.add(..) to accept any shape but that is not the case if you allows test1 (which is List<Rectangle>), test1 will not accept any shape that is not Rectangle.

Hope this helps.

NawaMan
+1  A: 

If this code worked, you could continue by inserting into test2 a Circle -- thus utterly breaking the guarantee that test1 makes, that only Rectangles will ever be inserted in it.

The general principle (language independent -- a matter of logic -- even though counter-intuitive): a bag of bananas is NOT a bag of fruit... in a world of mutable objects (the functional programming world, where every object is immutable once created, is MUCH simpler!). That's because you can add an apple to a bag of fruit (since an apple is a piece of fruit), but you can't add an apple to a bag of bananas (since an apple is not a banana).

BTW, this is very similar to the reason a square is not a rectangle (again, in a world of mutable objects): because given a (mutable) rectangle you can mutate the two sides independently, but, given a square, you can't. (In geometry, a square IS indeed a rectangle - but that's because, in geometry like in functional programming, there is no concept of "mutating" an object!-).

Alex Martelli