The “I can’t find the object I put in the map” code blooper of the day

This one is fairly easy to catch, but it was a self inflicted code blooper that had me thinking for a bit.
public class Key implements java.io.Serializable
{
String key;
public Key(String key)
{
this.key = key;
}
@Override
public String toString()
{
return key;
}
@Override
public int hashCode()
{
super.hashCode();
}
@Override
@SuppressWarnings("unchecked")
public boolean equals(Object obj)
{
boolean retval = false;
if (obj != null && getClass() == obj.getClass())
{
Key other = (Key)obj;
retval = other.getKey().equals(getKey());
}
return retval;
}
}
I used this class as a key into a Map. We would send this map over a serialized stream, and on the other side we couldn’t get the values by using the same keys (the keys are static finals/constants).
See if you can spot the error … it’s a bit obvious …
OK, you found it.
Yeah, it’s the hashCode(). You probably know about the equals()/hashCode() rule when using Maps.
Don’t know how that “super” got in there, but that was the problem. Simple of course. As a side note, I’ve been using Netbeans 6 and it has some interesting suggestions for genearting your equals and hashCode() methods. On the equals, I was a bit surprised to see it was using “getClass() == obj.getClass()“, I thought it would do “getClass().equals(obj.getClass())“, just because when I compare non primitive types I’m used to using the equals() method. Somehow this works, I guess because class definitions are loaded once? Intuitively I feel this is not the right way, but it works and seems to be accepted convention.
To be quite honest, I’ve been using “instanceof” for the longest time, and up until recently I didn’t know there was a debate about that one.
Filed under: Code Bloopers on October 17th, 2007

Class objects are unique per ClassLoader so the equals() method is the same as the == operator. Class.equals() is probably the cleaner expression since it doesn’t rely on you knowing how Class and ClassLoader are implemented, but in this case it’s such a fundamental, common class that you can treat it a little differently.
The instanceof thing is a good point too, but in all my years of programming / managing Java projects I don’t think I’ve ever seen that bite anyone as an actual bug.