ReviseAlgo Logo

Inheritance

Inheritance Basics

Examine IS-A relationships, subclass structural layouts, parent member visibility, and compile-time rules vs runtime layout execution.

Interview: Focuses on stack vs heap memory layouts during class hierarchy instantiation, IS-A vs HAS-A modeling, and visibility access modifiers.

Last Updated: June 13, 2026 10 min read

Inheritance is a mechanism in Java that allows a new class (subclass or child class) to inherit the state (fields) and behavior (methods) of an existing class (superclass or parent class). It establishes an IS-A relationship between classes, enabling code reuse, modularity, and runtime polymorphism.

IS-A vs. HAS-A

Inheritance represents an IS-A relationship (e.g., Car is a Vehicle). Composition represents a HAS-A relationship (e.g., Car has an Engine) and is often preferred to reduce class coupling.

Subclass Heap Layout

When a subclass object is instantiated, the JVM allocates a single contiguous block on the heap containing all parent instance fields followed by the subclass fields.

Single Inheritance

Java supports single class inheritance. A class can extend exactly one superclass, avoiding diamond conflicts of state inheritance.

Memory Layout of Subclass Instances

When a subclass is instantiated (e.g., Dog dog = new Dog(); where Dog extends Animal), memory allocation on the heap includes:

  • Object Header: Contains runtime details (mark word for locking/GC, class word pointing to the class metadata in the Metaspace).
  • Superclass Fields: Space is reserved for fields declared in the parent class (including private fields, though they are not directly accessible by subclass code).
  • Subclass Fields: Space is reserved for fields declared directly in the subclass.

Visibility and Access Control

Access modifiers determine which parent members are visible to the subclass:

  • private: Stored in the heap object but not accessible by subclass code.
  • default (package-private): Accessible only if the subclass resides in the same package as the superclass.
  • protected: Accessible by the subclass even if it resides in a different package.
  • public: Universally visible.

Common Pitfalls

  • Abusing Inheritance for Code Reuse: Extending a class just to reuse helper methods, violating the IS-A conceptual relationship and creating fragile hierarchies.
  • Violating the Liskov Substitution Principle (LSP): Writing subclass methods that change the expected contract or behavior of parent methods (e.g., throwing unexpected exceptions).

Best Practices

  • Prefer Composition over Inheritance: Use composite HAS-A relationships unless there is a true, long-term IS-A relationship.
  • Design for Extension or Prohibit It: Design classes explicitly with inheritance in mind (e.g., declare helper hook methods as protected) or mark classes as final to prevent extension.

Interview-Relevant Information

Q1: Why does Java not support multiple class inheritance?
Answer: To avoid the Diamond Problem and state conflict. If Class A defines a field x, and both Class B and Class C extend A and modify x, then Class D extending both B and C would inherit ambiguous and conflicting states.

Q2: If private fields of a superclass are not visible in the subclass, are they allocated in the subclass heap memory?
Answer: Yes. When a subclass object is instantiated, a single contiguous memory block is allocated on the heap containing all fields defined in the entire inheritance hierarchy (including private fields). They are present in memory but access is restricted by compile-time rules.

Quick Checklist

Can you distinguish IS-A from HAS-A modeling, trace how subclass objects are mapped on the heap, and explain why private parent fields are allocated but inaccessible? If yes, you understand inheritance basics.

Use Cases

Modeling clean hierarchical taxonomy models (e.g., UI Component hierarchy in Swing/AWT).

Creating base handler frameworks containing general lifecycle hooks (e.g., HttpServlet container base classes).

Common Mistakes

Extending a class solely to access some of its utility methods instead of implementing composition.

Creating complex, deeply nested inheritance structures that are fragile and hard to refactor.