DEV Community

Prabhat Kumar
Prabhat Kumar

Posted on

Java equals() Best Practice: instanceof vs getClass()

This learning is something I personally encountered in a SonarQube rule violation fix PR raised by Steven. It led me to revisit how we have historically written (often IDE-generated) the equals() method in Java—and why things are shifting now.

🛠️ The Old Way: instanceof

For years, IntelliJ and other dev tools used the instanceof check inside equals():

if (!(obj instanceof MyClass)) {
    return false;
}
Enter fullscreen mode Exit fullscreen mode

This seemed fine—but there’s a hidden trap. It allows equality between subclass and superclass, which can violate the symmetry contract of equals():

a.equals(b) should return the same result as b.equals(a).

However, subclasses may have additional fields that the superclass doesn't compare—leading to inconsistent or buggy behavior in collections like HashSet, HashMap, or even in sorting and caching.

🚀 The Modern Approach: getClass()

IntelliJ and SonarQube now recommend:

if (obj == null || getClass() != obj.getClass()) {
    return false;
}
Enter fullscreen mode Exit fullscreen mode

This enforces strict class equality—avoiding the risk of broken symmetry and ensuring predictable behavior across use cases.

🧠 Why Does This Matter?

The equals() contract (reflexive, symmetric, transitive) has existed since Java 1.0.

But tools started enforcing this best practice in recent years due to:

  • Bugs discovered in real-world code.
  • New Java features like records and sealed classes.

✅ Key Takeaway

If your class is not designed for subclass comparison, prefer using getClass() in equals()—it’s safer and more predictable.

Top comments (0)