I wrote this small code to understand generics more clearly.But when i tried compiling,i got 6 errors which i have marked here in the code.Without those 6 lines,the code compiles fine.I don't understand why list a and b can't accept both Animal and Dog objects.Also why list c and d can accept only Dog objects!!.Please help,I'am having a hard time with this thing.
It's all about correctly understanding what the wildcard means.
List<? extends Animal> doesn't reference a list that can take any Animal or subclass. If that's what it did there'd be no need for it - a List<Animal> already does that. List<? extends Animal> holds a reference to a Listof a specific type, and that specific type can be Animal or a subclass.
So these are all valid initialisations:
Now, the compiler will only allow actions is can guarantee to be type safe. And the compiler only knows about the reference type. So what objects can you safely put into all these? Not a Dog, that wouldn't fit into an ArrayList<Cat>()*. And a similar argument will apply to any other object. In fact, there is no object you can safely put into every list that reference can point to (you can safely add null, but that's all).
You can use a similar argument for the other case. What can a List<? super Dog> hold a reference to? A List<Dog>, a List<Animal> or a List<Object>. You can safely put a Dog inside all of these. You can safely put an instance of any subclass of Dog in all of these. But you can't put a plain Animal into a List<Dog>. And again the compiler only knows about the reference type, so it will only allow actions you can safely perform on all these lists.
Does that help?
[* Edit: I know you could argue that the Cat class doesn't exist, so this shouldn't be a problem. But the compiler doesn't know what classes will be added in the future.]
Joined: Oct 12, 2012
Ah! So you can't add anything to the List<? extends Animal>! Thank you so much! It's much more clearer now.