2

Why can't I do this:

LinkedList<Fruit> myFruits = new LinkedList<Apple>();

Error message:

Type mismatch: cannot convert from LinkedList<Apple> to LinkedList<Fruit>

Where is the difference to the following?

Fruit fruit = new Apple();
Martin Thoma
  • 124,992
  • 159
  • 614
  • 958
  • possible duplicate of [Is \`List\` a subclass of \`List\`? Why aren't Java's generics implicitly polymorphic?](http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicit) – jlordo Jan 03 '13 at 18:27

4 Answers4

10

Consider what you can do with a LinkedList<Fruit> - and think about what you'd want this code to do:

LinkedList<Apple> apples = new LinkedList<Apple>();
LinkedList<Fruit> fruits = apples;
fruits.add(new Banana());

Apple apple = apples.getFirst(); // Safe at compile time, but it's a Banana!

The conversion is the only place it makes sense for this to fail at compile-time. Now what you can write is:

LinkedList<? extends Fruit> myFruits = new LinkedList<Apple>();

... and then the compiler won't let you add anything to the list, as it doesn't know what the real element type is. Likewise you coudl write:

LinkedList<? super Apple> apples = new LinkedList<Fruit>();

Now you can add apples to the list, but you can't get apples out of the list, as again you don't know what the type would be.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
1

Polymorphism simply doesn't apply to generic types.

LinkedList<Fruit> is not same as LinkedList<Apple> even though Fruit is a super class of Apple.

Refer to this Answer for the reason.

Community
  • 1
  • 1
PermGenError
  • 45,977
  • 8
  • 87
  • 106
0

Because then you could add an Orange to myFruits and that shouldn't work as the actual list is a list of Apple

For example (If you could make this);

List<Apple> myApples = new LinkedList<Apple>();
List<Fruit> myFruits = new LinkedList<Apple>();
myFruits.add(new Orange());

now myApples got an Orange in it

Aviram Segal
  • 10,962
  • 3
  • 39
  • 52
0

A simple assignement is allowed because the reference is copied and the original is left untouched.

Apple apple = new Apple();
Fruit fruit = apple;
fruit = new Banana(); // apple is not touched and is still an Apple

whereas (AtomicReference to be a simple collection)

AtomicReference<Apple> apple = new AtomicReference<>(new Apple());
AtomicReference<Fruit> fruit = (AtomicReference) apple; // warning but compiles.
fruit.set(new Banana()); // this alters apple as well, making it invalid!
Apple apple2 = apple.get(); // throws ClassCastException.
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130