Key to Generics


Note: This article assumes that you are clear about the is-a concept in OO. i.e. A subclass object is-a superclass. For example, an Integer is-a Number (because Integer extends Number). Thus, every Integer is-a Number but every Number is not necessarily an Integer. It could be a Double or Long (or any other Number) also.

Understanding Generics is quite simple, if you understand the following three basic principles:

1. Type Safety: 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. At 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? In technical jargon, this is called "type safety".

That's the fundamental thing behind Generics and is the hardest to absorb, so, read it again and again until you remember it by heart before proceeding further.

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. In other words, "? extends Apple" does not mean "any class that extends Apple". It means a specific but unknown class that extends Apple.

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 in it?)
Q. So, when you take out a thing from a sack of "? extends Apple", what do you get?
(Hint: An Apple for sure. But are you sure you will get a Fuji Apple? 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". 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? Can you call it 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, given listOfSuperApple, which is declared as List<? super Apple>, which of these statements should work?

listOfSuperApple.add(anApple);
listOfSuperApple.add(someFruit);
listOfSuperApple.add(aMacintoshApple);

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. Which of these statements should work then?

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?

Note: The answers to the above short questions are not given to encourage you to write small test programs and confirm your understanding.