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();
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();
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.
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.
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
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.