title: Understanding equals method
body: <p>J. Bloch in his effective Java provides a several rules for the implementation for equals method. Here they are:</p>
  <blockquote>
  <p>• Reflexive: For any non-null reference value x, x.equals(x) must
  return true.</p>
  <p>• Symmetric: For any non-null reference values x and y,
  x.equals(y) must return true if and only if y.equals(x) returns true.</p>
  <p>• Transitive: For any non-null reference values x, y, z, if
  x.equals(y) returns true and y.equals(z) returns true, then
  x.equals(z) must return true.</p>
  <p>• 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.</p>
  <p>• For any non-null
  reference value x, x.equals(null) must return false.</p>
  </blockquote>
  <p>But later in the book he mentioned so-called Liskov substitution principle:</p>
  <blockquote>
  <p>The Liskov substitution principle says that any important property of
  a type should also hold for its subtypes, so that any method written
  for the type should work equally well on its subtypes</p>
  </blockquote>
  <p>I don't see how it ties to the <code>equals</code> contracts. Should we actually adhere to it while writing the equals implementation?</p>
  <p>The question is about implementing the method for subclasses.  Here is the example from the book:</p>
  <pre><code>private static final Set&lt;Point&gt; unitCircle;
  
  static {
      unitCircle = new HashSet&lt;Point&gt;();
      unitCircle.add(new Point(1, 0));
      unitCircle.add(new Point(0, 1));
      unitCircle.add(new Point(-1, 0));
      unitCircle.add(new Point(0, -1));
  }
  
  public static boolean onUnitCircle(Point p) {
      return unitCircle.contains(p);
  }
  
  public class CounterPoint extends Point {
      private static final AtomicInteger counter = new AtomicInteger();
  
      public CounterPoint(int x, int y) {
          super(x, y);
          counter.incrementAndGet();
      }
  
      public int numberCreated() { return counter.get(); }
  }
  </code></pre>
  <p>and the following implementation:</p>
  <pre><code>// Broken - violates Liskov substitution principle (page 40)
  @Override public boolean equals(Object o) {
      if (o == null || o.getClass() != getClass())
          return false;
      Point p = (Point) o;
      return p.x == x &amp;&amp; p.y == y;
  }
  </code></pre>
  <p>Ok, violates and what then? I don't understand.</p>