Java Generics – were they a good idea?


No. I think that all told, while implemented with the best of intentions, Java Generics were a bad idea. While they do provide welcome and useful functionality in some cases, overall the costs outweigh the benefits.

Cost

This new language feature and its use throughout the new Java 1.5 libraries have added a significant amount of complexity to the world of the Java developer. From the slightly counter intuitive (e.g. List<String> is not a subtype of List<Object>) to the profoundly metalicious (e.g. Enum<E extends Enum <E>>), generics can be subtle and difficult to fully understand for the average Java developer. Ask the average Java 1.4 programmer to read and explain this to you:

TypeVariable is the common superinterface for type variables of kinds. A type variable is created the first time it is needed by a reflective method, as specified in this package. If a type variable t is referenced by a type (i.e, class, interface or annotation type) T, and T is declared by the nth enclosing class of T (see JLS 8.1.2), then the creation of t requires the resolution (see JVMS 5) of the ith enclosing class of T, for i = 0 to n, inclusive. Creating a type variable must not cause the creation of its bounds. Repeated creation of a type variable has no effect. (http://java.sun.com/j2se/1.5.0/docs/api/java/lang/reflect/TypeVariable.html)

Yea.

Benefits

So what do we get for all this? The way I see it, there are really only two benefits to Java generics:

(1) They allow the compiler to catch some programming errors that would otherwise be detected at runtime as ClassCastExceptions (i.e. generics can prevent you from placing an Integer into a List of Strings).

(2) They make *certain* declarations more “self-documenting”. If I see a method signature that declares a parameter as a List of Strings (List<String>) it is much clearer to me how to use the method correctly and is more reliable than the documentation, if it even exists.

Net net

For me, it’s not worth it. So I have to cast more and perhaps catch some programming errors at runtime. In my experience the vast majority of ClassCastExceptions are the result of programming errors that you will catch very early while running and testing your code anyway. You fix the code and move on. Also, if you structure your error handling correctly, you should not need to wrap each cast in a try/catch block. Bottom line: the core problem generics aim to solve is not that bad of a problem.

As for (2) I would have to say that for every example of code that generics have made easier to understand there is at least one example where it has done just the opposite. Furthermore, in real-world programming with real-world class names method signatures become multi-line monsters that are quite ugly, hard to read, and a real burden to type (so much for the keystroke savings of not needing casts).

Adding language features are a big deal. You can’t undo them and they can have far reaching consequences. Java as a language, its documentation, the number of concepts its user has to manage, and the user’s learning curve have become much more complex for marginal benefit. Any addition to the language should have the effects of making programs easier to both read and write, making concepts simpler to express, and enabling the programmer to be more productive. If anything I would have liked to have seen the addition of multiple dispatch to Java (sometimes called generic methods (yes confusing) – perhaps more on this in another post).

Do I use it?

For the cases where I have no choice (grrr) and for the cases where it truly is a harmless perk (like Map<String, List>), yes, sometimes. Otherwise I avoid it.

About these ads
  1. Ability to get rid of ClassCastExceptions alone is good enough reason to use generics.

  2. You seem to overlook the possibly greatest advantage: The ability to reduce the duplications of code when writing highly similar classes/methods. While some of these cases can be realistically solved by using Object instead of the specific relevant sub-types, respectively Generics, these solutions are often ugly, error prone, and necessitate weird casts in the code.

    That said: Grafting on a feature at so late a stage, as was the case with Generics, often leads to sub-optimal solutions compared to a feature that is built-in in one of earliest versions of the language.

  3. Stunning! Keep it up. :-D

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: