I was having a conversation with Jonathan a few days ago about generics in Java. We were dusting off some old code, correcting half remembered bugs (the best kind) and giving it a shiny new coat of paint in the form of java generics and annotations.
I’ll discuss annotations in later posts but our conversations hightlighted what I’ve discovered is an all too common misunderstanding about subtyping with java generics. Just to be very clear, I believe java generics are a very very good thing. However, they require a bit of caution when applying to legacy code. SUN already have an excellent guide to generics which is part of their Java Tutorial
However, I’ll just draw the readers attention to the two most common errors I’ve seen. Both relate to over-specialisation of a class following the application of generics.
The Java tutorial cites a simple operation on collections such as the outputting of a list.
void printCollection(Collection c) {
Iterator i = c.iterator();
for (k = 0; k < c.size(); k++) {
System.out.println(i.next());
}
}
And a naive attempt at writing it using generics (and the new for loop syntax):
void printCollection(Collection<Object> c) {
for (Object e : c) {
System.out.println(e);
}
}
This looks really nice but the problem is that the printCollection now must be an Object and ONLY an Object. It’s very unlikely that was what was intended by the original author. This seems to be the first and most common mistake that every Java programmer who starts experimenting with generics makes. Yet I can see how this kind of thing could easily pass a unit test, one which uses a dummy java.lang.Object… ooops ![]()
Which leads us to non-trivial statements like the following.
public static <T extends Object & Comparable>
T max(Collection coll)
Which means Max is calculated on a collection where each element extends T and returns a value which is of type T that extends type java.lang.Object (for backwards compatibility) and is comparable in itself or is derived from a comparable type
So generic programming actually requires more careful thoughts and explicit statement about type-safety than non-generic.
I’m not actually sure this is an altogether good thing as it’s arguably impeding the adoption of generics, irregardless of their uses in the creation of extremely reusable and modular patterns.
