Specification of the equals(Object) Method in Java

The specification of Java's standard libraries imposes certain invariants that must be satisfied by any equals(Object) method we define.

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.

The "provided no information...is modified" qualification on the next-to-last invariant helps to explain why we have been using immutable data types so far in this course. With mutable data types, everything becomes more complicated. In particular, x.equals(y) may return true for one call but return false a moment later, after some concurrent thread has changed the state of x or y.

When we define an equals method, we must also define a hashCode method:

Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.

For debugging: Click here to validate.