Feb 262005

Last night while I was working on some coding on the L here in Chicago, I realized something very interesting about the Java 5.0 generic Map interface. It seems that certain methods on this class have not been updated to support generics. Specifically the get method has this signature:

This seems to me to be a glaring bug in the JDK interfaces. Well, I looked over on the bug list at Sun and found this bug:


Sun’s explanation for this method signature is as follows:
> – “public V get(Object key)”
> – “public boolean containsKey(Object key)”
> – “public boolean containsValue(Object value)”

> These signatures are as intended. Given a HashMap<Integer ,String>, for example, one could reasonably want to invoke get(n) where n is a Number. It may be the case that n is in fact an Integer, in which case the operation will proceed normally; null may legitimately be returned otherwise.

I have to completely disagree on this explanation. What Sun has done is allow Maps to be semi safe. Here’s why:

This compiles and runs and fails everytime. There is no compiler check that says, “hey, dude, you this map takes Key’s not String’s.” This means that nasty bugs can be introduced into code that should be safe using generics. The problem is that this code won’t throw an exception to tell the developer that their code is incorrect. It just returns null. So, the developer has to walk through the code line by line and double check that every call to the get method is correct.

In addition, Sun’s little rant about wanting to pass in super classes seems incorrect. If you want a Map that takes super-classes you should make it like this:

If you want to ensure type safety then you must force the developer to cast when calling the get method and possibly have a ClassCastException thrown. Therefore, code that implements their explanation above would look like this:

I’d like to hear other peoples thoughts on this topic. Perhaps an API change can be made in 6.0.