The Artima Developer Community
Sponsored Link

The Coding Curmudgeon
Some Objects are More Equal Than Others
by Cay Horstmann
May 8, 2003
Summary
Many Java programmers believe that they should include an instanceof test in equals methods. Many authors egg them on. This article explains why this is very wrong and muddleheaded in almost all cases, and urges programmers to test for equality of classes instead.

Advertisement

The Java Language Specification states that the equals method of any class should be reflexive, symmetric (well, almost...null.equals(x) is different from x.equals(null)), and transitive.

That's easy enough to achieve:

public Employee
{
public boolean equals(Object other)
{
if (getClass() != other.getClass()) return false;
// cast other to Employee and compare fields
. . .
}
}

What bugs me is how many programmers do something different and dangerous, and how many authors egg them on. If you look at the implementations of equals in the source of the standard library (about 150), you will find that the majority use an instanceof test instead.

public Employee
{
public boolean equals(Object other)
{
if (!(other instanceof Employee)) return false;
// cast other to Employee and compare fields
. . .
}
}

This is a crummy idea. In many (most?) cases, a subclass will want to override equals by comparing the superclass fields and the subclass fields, like this:

public Manager extends Employee
{
public boolean equals(Object other)
{
. . .
if (!super.equals(other)) return false;
// cast other to Manager and compare fields
return bonus == ((Manager)other).bonus;
}
}

But now equals has become seriously asymmetric:

That problem can be avoided easily. Does it ever make sense for an Employee to equal a Manager? No. Just forget about instanceof and test for equality of classes instead.

Why don't more authors mention this?

For example, Josh Bloch has a chapter on equals in his Effective Java book, and he never once mentions the getClass() != other.getClass() test.

Instead, he pontificates about a rather pointless example with Point and ColoredPoint classes where equals does not take the point's colors into consideration.

Why is there a stubborn refusal in the Java literature to recognize the obvious?

If a class is final it doesn't matter. But there are lots of non-final classes with bad definitions of equals, for no better reason than that the folks who should know better set a bad example.

That's my pet peeve of the day.

Talk Back!

Have an opinion? Readers have already posted 28 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Cay Horstmann adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Cay Horstmann is a professor of computer science at San Jose State University. He is an experienced professional programmer and was VP of Technology and CTO at Preview Systems Inc. He wrote many successful professional and college books, including Core Java (with Gary Cornell), Big Java, Big C++ (with Tim Budd), and OO Design & Patterns.

This weblog entry is Copyright © 2003 Cay Horstmann. All rights reserved.

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us