Hard👤 8-15 years 3 min read

equals/hashCode Under Inheritance — Interview Questions

Asked inAmazonOracleMicrosoftDeloitte
#equals#hashcode#inheritance#symmetry#hibernate
Report issue

⚡ Short Answer

Adding a value field in a subclass makes it nearly impossible to keep equals() symmetric and transitive with its superclass — the classic Point/ColorPoint problem. You get two imperfect options: use getClass() (breaks Liskov — a subclass is never equal to its parent) or instanceof (can break symmetry/transitivity). The clean fixes: prefer composition over inheritance for value types, or define equality on a stable business key. With Hibernate, proxies and generated ids make identity-based equals dangerous.

Coffee Chat Question

Concept Made Simple

How does the equals()/hashCode() contract break under inheritance, and with ORM proxies?

🧠Mind Map Answer

Remember It Faster

The trap: once a subclass adds a significant field, no equals() can satisfy reflexive + symmetric + transitive with the parent at the same time. It's a genuine design conflict, not a coding mistake.

getClass()Symmetric, but breaks Liskov (no subtype equality)
instanceofAllows subtype equality, risks asymmetry
Best fixComposition over inheritance for value types
HibernateUse a business key, not the generated id

Hibernate/JPA: entities are wrapped in proxies (so getClass() != real class → use instanceof), and the id is null until persisted (so id-based hashCode changes after save, corrupting HashSets). Equality on an immutable natural/business key avoids both.

Key takeaway: value equality and inheritance don't mix cleanly — favour composition, base equality on immutable business keys, and never key a HashSet on a field that changes after construction/persistence.

⌨️Hands-on Keyboard

Learn by Doing

java
@Entity
class User {
    @Id @GeneratedValue Long id;          // null until persisted!
    @Column(unique = true) String email;   // stable business key

    @Override public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof User other)) return false;
        return email != null && email.equals(other.email);  // key, not id
    }
    @Override public int hashCode() {
        return Objects.hashCode(email);     // stable across persist
    }
}

🔥What If?

Think Beyond the Expected

Why is basing a JPA entity's hashCode on its @GeneratedValue id dangerous?

Because the id is null before the entity is persisted and gets assigned on flush — so an entity's hashCode changes after you've already added it to a HashSet/HashMap. Once the hash changes, the collection can't find the element (it's in the wrong bucket), leading to duplicates, lost lookups, and leaks. Base equals/hashCode on an immutable business key (email, natural id) that's set at construction and never changes, so identity is stable across the entity's whole lifecycle.

😂Real World

Any project mixing JPA entities with HashSet/HashMap membership hits this: entities 'disappear' from sets after being saved, or bidirectional associations behave oddly, all because id-based hashCode changed on flush. Teams standardise on business-key equality (or documented reference equality) to keep collections correct.

🎯Interviewer's Expectation

Keywords they're listening for:

subclass value field breaks symmetrygetClass breaks Liskov, instanceof risks asymmetrycomposition over inheritancebusiness key over generated idHibernate proxy + null-id pitfalls

⚠️Common Mistakes

  • Basing entity hashCode on a generated id
  • Mixing inheritance with value equality
  • Using getClass() and being surprised proxies never match

Best Practices

  • Prefer composition for value types
  • Use immutable business keys for entity equality
  • Consider records for simple immutable value objects

🔁Follow-up Questions

  • 1getClass() vs instanceof in equals — trade-offs?
  • 2Why do records sidestep some of these issues?
  • 3How do Hibernate proxies affect getClass() comparisons?

🧩Related Technologies

HibernateJPArecordsHashSet

Continue Learning with AI

Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly — AI is your learning companion, not a shortcut.

Plain-language foundations

I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner.

Topic: Object Contract (Advanced Java)
Interview question: "How does the equals()/hashCode() contract break under inheritance, and with ORM proxies?"

Please:
1. Explain the core idea in simple, plain language, using an everyday analogy.
2. Define any technical terms you use.
3. Walk through one small, concrete example.
4. Finish with a single sentence I can easily remember.

Keep the tone friendly and assume I'm new to this topic.
Open inChatGPTGeminiClaude

Was this answer helpful?

Support our platform by exploring our recommended products.

As an Amazon affiliate, purchases through these links may earn us a small commission — at no extra cost to you. It helps keep Full Stack Interview Guru free.

Related Questions