I think you are over complicating it in your mind. It is quite simple actually, if you understand the following three basic principles:
1. The whole (ok, not whole but one of the main) purpose of having generics is to avoid putting random things in any collection. After all, you want things organized. You don't want to put apples in a sack of potatos. And when you are given a sack of apples, you expect apples to come out and not potatos. As the same time, if you are given a "basket of fruit" as a gift,
you should be able to put an orange, an apple, a mcintosh apple, or any other fruit into it. Right? And when you pick a fruit from that basket, do you always expect to get an apple? No, right?
That's the fundamental thing and the hardest to absorb (I bet you are rolling your eyes
).
Now, the simpler stuff:
2. ? extends Apple : This means "of a class that extends Apple". Therefore, List<? extends Apple> means a sack of some variety of Apple. Mcintosh? Probably. But you don't know.
Q. So when you are given a sack of "? extends Apple", can you put a Mcintosh in it? If you have any doubt, read point 1 again. (Hint: Do you want to mess up your sack of Fuji apples by putting a Mcintosh apple it it?)
Q. So when you take out stuff from a sack of "? extends Apple", what do you get? An Apple for sure. (You don't mind if it is a Mcintosh or a Fuji, do you? As long as you don't get a Potato, you are good
)
3. ? super Apple: This means "of a class that is a super class of Apple". Therefore, List<? extends Apple> means a sack of something of which an Apple is a kind. Let's call it "it". Now play Jeopardy. So, What do you call a sack of something of which an Apple is a kind? A sack of fruits. Are you sure? Can you not call it a sack of food items? or A sack of Mcintoshes? (Hint: Every apple is a kind of fruit. Every apple is a kind of food item. Is every apple a kind of Mcintosh?) So which of these statements should work?
listOfsuperApple.add(anApple);
listOfsuperApple.add(someFruit);
listOfsuperApple.add(aMac);
Read 1 again, if in doubt.
Q. So when you take out stuff from a sack of "? super Apple", what do you get? Apple? Probably. A fruit? probably. Some food item? probably. Are you sure? No. So what are you sure of? Well, its something, but you don't know what. So you are sure of nothing, really. So which of these statements should work?
Apple a = listOfsuperApple.get(0);
Fruit a = listOfsuperApple.get(0);
FoodItem a = listOfsuperApple.get(0);
Object a = listOfsuperApple.get(0);
Read 1 again, if in doubt.
Q. So when you are given a sack of "it", can you put any apple in it? Well, can you not put any apple in a sack of fruits? in a sack of food items? In a sack of apples?
Read 1 again, if in doubt.
That's it! If you understand point 1, you will never miss any question on generics. Ever!
Quiz: What would List<?> mean? What can you put in it and what can you take out from it?