Monday, February 07, 2005

Java Generics vs the KISS principle

The designers of JSR 014 Java Generics really missed the "KISS principle"

Before Java 5, we only had to deal with a simple class-cast exception:

ArrayList list = new ArrayList();
list.add( new Bar() );
Foo foo = (Foo) list.get(0); // class cast exception!

This problem sometimes happened at runtime. It is generally a small problem, easily eliminated. Usually good unit tests and functional testing found the problems. The problem was simple enough to understand and explain. Usually even the most junior developers could understand this issue and learn to avoid it with little difficulty.

In Java 5 we now have to deal with Java Generics:

ArrayList list = new ArrayList();
list.add( new Bar() );
Foo foo = list.get(0); // compile time error :)

Everyone's initial impression is "Wow that's a great idea!" Unfortunately the difficulties of Java Generics are not touched in such a simple example. Just take a look at Java thoery and practice: Generics gotchas and the Java Generics FAQs for details about the special problems introduced by generics.

So instead of having to work around one simple class cast problem, we have to work around a complex mess of special rules and gotchas! I have seen experieced developers (myself included) scratching our heads trying to get through the gotchas introduced by Java Generics. All the special rules and problems introduced in Generics are very hard to understand and memorize. Thus Java Generics has violated the "KISS principle." Things really don't work as expected in Java Generics. We have traded one simple problem for a hundred pages of special rules! (Just look at the size of the FAQ)

It will be interesting to see what efforts are made in future JSRs to correct the gotchas in Java Generics. I would imagine adding something to keep the variable's Generic type information at runtime would help.

No comments: