Generics in Java have always been both a source of fascination and frustration for me. I’ll openly admit that I still don’t know enough about the subject, even though I’ve worked with Java for four years now.
The very first thing that puzzled me is that contrary to “regular” classes in Java, generic elements don’t really have superclasses to speak of. Consider the following example:
Object obj; String str = "Hello"; obj = str;
Object as it’s highest superclass. Thus, it’s legal to assign a
String to an
Object — obviously, one can only call the methods of the
Object class after such an operation.
Now consider this example:
ArrayList<Object> listOne; ArrayList<String> listTwo = new ArrayList<String>(); listOne = listTwo; listOne.add(new Integer(1)); String str = listTwo.get(0);
In this example, we attempt to assign a list of Strings to a variable with the type “list of Objects”. If this would work, we could add another type of object (say, an
Integer) to the list. After this,
listTwo doesn’t just contain Strings anymore, which leads to trouble on the last line of our code. Thankfully, Java doesn’t allow this to happen — line
2 3 in our example will give us an error if we attempt to compile the code.
The best quick explanation of generics/superclasses in Java that I’ve found is in a book called Generics in the Java Programming Language (PDF link), written by Gilad Bracha:
For example, if the department of motor vehicles supplies a list of drivers to the census bureau, this seems reasonable. We think that a
List<Person>, assuming that
Driveris a subtype of
Person. In fact, what is being passed is a copy of the registry of drivers. Otherwise, the census bureau could add new people who are not drivers into the list, corrupting the DMV’s records.
The book is a comprehensive Java generics resource, and discusses even the most advanced concepts in a highly understandable form. Don’t forget to read The Tapir’s Tale blog post or Angela Lanker’s website, either.