Sobes.tech
Middle

How to properly override the equals method in Java?

sobes.tech AI

Answer from AI

// Example of a minimally correct override of equals
class MyClass {
    private int id;
    private String name;

    public MyClass(int id, String name) {
        this.id = id;
        this.name = name;
    }

    @Override // Mandatory annotation
    public boolean equals(Object o) {
        // 1. Check for identity
        if (this == o) return true;
        // 2. Check for null and class match
        // Use getClass() for strict check
        if (o == null || getClass() != o.getClass()) return false;
        // 3. Cast
        MyClass myClass = (MyClass) o;
        // 4. Compare significant fields
        return id == myClass.id &&
               // Use Objects.equals for object comparison (handles null)
               Objects.equals(name, myClass.name);
    }
}

Rules for correct overriding of equals (according to Object.equals contract):

  • Reflexivity: For any non-null reference x, x.equals(x) should return true.
  • Symmetry: For any non-null references x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • Transitivity: For any non-null references x, y, and z, if x.equals(y) and y.equals(z) are true, then x.equals(z) should be true.
  • Consistency: For any non-null references x and y, multiple invocations of x.equals(y) should consistently return true or false, provided no information used in comparisons has changed.
  • For any non-null reference x, x.equals(null) should return false.

It is recommended to use Objects.equals(obj1, obj2) for safe object comparison, as it correctly handles null.

Always override hashCode() when overriding equals() in accordance with the general contract of Object.hashCode: if two objects are equal according to equals(Object), their hash codes, as returned by hashCode(), must be the same. The converse is not required. Failing to follow this rule will lead to incorrect behavior of hash-based collections (e.g., HashMap, HashSet).

// Example of a corresponding hashCode for MyClass
class MyClass {
    private int id;
    private String name;

    // ... constructor and equals as above ...

    @Override
    public int hashCode() {
        // Use Objects.hash for convenient hash calculation
        return Objects.hash(id, name);
    }
}

You can generate equals and hashCode methods automatically using IDEs (IntelliJ IDEA, Eclipse), which is a good practice.

Use instanceof instead of getClass() only if the class is part of an inheritance hierarchy and you want objects of superclasses and subclasses to be considered equal if they have the same state. In most cases, it is preferable to use getClass() for strict checking.