Implementing equals() the right way

      No Comments on Implementing equals() the right way

At first sight, implementing equals() doesn’t seem fairly hard. Unfortunately, it turns out that writing a correct equality method is surprisingly difficult:

http://java.sun.com/javase/6/docs/api/java/lang/Object.html

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

In fact, after studying a large body of Java code, the authors of a 2007 paper concluded that almost all implementations of equals methods are faulty.1

There are quite a lot of HowTos available on the web. One of the best might be the article “How to Write an Equality Method in Java” by Martin Odersky, Lex Spoon, and Bill Venners.

So instead of repeating all the pitfalls you have to avoid, I’ll give you a sample implementation2 of the equals()-method that follows the general contract using the example of an imaginary class Point:

public boolean equals (final Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (this.getClass() != obj.getClass()) {
      return false;
    }
    final Point other = (Point) obj;
    if (this.x != other.x) {
      return false;
    }
    if (this.y != other.y) {
      return false;
    }
    return true;
  }

Be careful: Whenever you overwrite equals() it is generally necessary to override the hashCode()-method, too!

If you want to learn more about this topic, I suggest, you have a look at Joshua Bloch’s Effective Java Second Edition. Addison-Wesley, 2008.

[1] Vaziri, Mandana, Frank Tip, Stephen Fink, and Julian Dolby. “Declarative Object Identity Using Relation Types.” In Proc. ECOOP 2007, pages 54–78. 2007.
[2] http://www.artima.com/forums/flat.jsp?forum=226&thread=259279&start=30&msRange=15

Leave a Reply

Your email address will not be published.