dagblog.
← Archive

Do you use getClass or instanceof in your equals method?


What better way to start than by taking a shot at my own team? Once again I made a fool of myself. Several classes in one of our modules had the following implementation of equals.

01 public boolean equals(Object obj) {

02 if (this == obj)

03 return true;

04 if (obj == null)

05 return false;

06 if (getClass() != obj.getClass())

07 return false;

08 final Foo other = (Foo) obj;

09 if (something == null) {

10 if (other.something != null)

11 return false;

12 } else if (!something.equals(other.something))

13 return false;

14 return true;

15 }

Java2html

At first glance it’s nothing special, and the code will work. That is, until we decide to start using a class with this equals implementation

in Hibernate and it becomes an entity bean. Then line six may cause us some trouble. What happens? Hibernate can hand us proxy objects (Lukáš Bartoň originally pointed this out to me), in which case calling this method will always return false. The fix is simple, though it won’t solve everything: use instanceof.

Why doesn’t that solve everything? If we use instanceof this way, we break the symmetry of the equals contract for a superclass (A) and subclass (B). It will no longer hold that a.equals(b) == b.equals(a). We can, of course, adjust equals to make it work. Personally, I prefer instanceof.

The issue of instanceof versus getClass in equals Methods is covered quite well by Joshua Bloch and Bill Venners. I highly recommend reading their article.

While fixing the equals methods, I wondered where the code came from. Of course, we’d had Eclipse generate it. I was about to curse Eclipse for generating the wrong code. Fortunately, I didn’t, because Eclipse actually offers an option to use instanceof when it generates equals. Which leads me to conclude that the IDE is smarter than the monkey …

Sources

Medium version

Related articles

Related CZ Podcast episodes