DEV Community

Tin Trinh
Tin Trinh

Posted on

Write effective code for equals method

Why do we need to override the equals method

Q: When to override the equals method?
A: If the class not override it and the object identity is merely not enough for equality.

A right implementation of equals makes the instance object to serve as map keys or set elements with predictable and desirable behavior

equals method is characteristic:

  • reflexive: an object should equal itself.
  • symmetric: if object A equals object B, object B should equal with object A as well
  • transitive: if A equals B, B equals C, so A should equal C.
  • consistency: the same result will return no matter how many times you run it.

And one more important characteristic that only exists in the OOP world.
Lisov substitution principle says that any important property of a type should also hold for all its subtypes so that any method written for the type should work equally well on its subtypes.
What does that mean?
For example:

class A {
   int size;
}

class B extends A {
    Color color;
}

A a = new A(1);
B b = new B(1, Color.RED);

a.equals(b) // should return true

Extend instantiable class and add a value component to it violate the transitive rule easily.
Like java.util.Timstamp extend from java.util.Date and add nanoseconds field.

One common mistake this that do the null checking and getClass() to compare in the equal method. That will make the equals method not able to have the Lisov substitution characteristic.

Not necessary to null checking in the equals method. Simply cast it to the object we want so we could have the accessor to it.

public boolean equals(Object o) {
  if (!(o instanceof MyType)) {
      return false;
  }
}

Conclusion

High quality equals method:

  1. Use the == operator to check if the argument is a reference to this object: Performance optimization
  2. Use instanceof to check if the arg has the correct type. No need to do the null check.
  3. Cast argument to correct type.
  4. Check if a file of the arg matches the corresponding field: if float or double field we need to call Float.compare and Double.compare the method, if the field is object filed call the equals method recursively. To avoid the possibility of NullPointerException, using Objects.equals(Object, Object)

After writing the equals method.
Is it symmetric? Is it transitive? Is it consistent?

Use the AutoValue framework to write hashCode and equals more easily.

Top comments (1)

Collapse
 
bfuculsion profile image
Benjamin Follis

In Java, don't forget to override the hashCode method as well, otherwise maps won't treat them as equal.