## Why is this an issue?

A key facet of the `equals` contract is that if `a.equals(b)` then `b.equals(a)`, i.e. that the relationship is symmetric.

Using `instanceof` breaks the contract when there are subclasses, because while the child is an `instanceof` the parent, the parent is not an `instanceof` the child. For instance, assume that `Raspberry extends Fruit` and adds some fields (requiring a new implementation of `equals`):

    Fruit fruit = new Fruit();
    Raspberry raspberry = new Raspberry();

    if (raspberry instanceof Fruit) { ... } // true
    if (fruit instanceof Raspberry) { ... } // false

If similar `instanceof` checks were used in the classes' `equals` methods, the symmetry principle would be broken:

    raspberry.equals(fruit); // false
    fruit.equals(raspberry); //true

Additionally, non `final` classes shouldn’t use a hardcoded class name in the `equals` method because doing so breaks the method for subclasses. Instead, make the comparison dynamic.

Further, comparing to an unrelated class type breaks the contract for that unrelated type, because while `thisClass.equals(unrelatedClass)` can return true, `unrelatedClass.equals(thisClass)` will not.

### Noncompliant code example

    public class Fruit extends Food {
      private Season ripe;

      public boolean equals(Object obj) {
        if (obj == this) {
          return true;
        }
        if (obj == null) {
          return false;
        }
        if (Fruit.class == obj.getClass()) { // Noncompliant; broken for child classes
          return ripe.equals(((Fruit)obj).getRipe());
        }
        if (obj instanceof Fruit ) {  // Noncompliant; broken for child classes
          return ripe.equals(((Fruit)obj).getRipe());
        }
        else if (obj instanceof Season) { // Noncompliant; symmetry broken for Season class
          // ...
        }
        //...

### Compliant solution

    public class Fruit extends Food {
      private Season ripe;

      public boolean equals(Object obj) {
        if (obj == this) {
          return true;
        }
        if (obj == null) {
          return false;
        }
        if (this.getClass() == obj.getClass()) {
          return ripe.equals(((Fruit)obj).getRipe());
        }
        return false;
    }

## Resources

- CERT, MET08-J. - Preserve the equality contract when overriding the equals() method