Inheritance
How Java inheritance works — extends, super, method overriding, and when to use inheritance vs composition in real enterprise projects.
Last reviewed: January 2025
🔍 What Is It?
Inheritance Hierarchy
Object (root of all Java classes)
└── Animal
├── Dog
└── CatKey Keywords:
- →
extends— inherit from a class (single inheritance only) - →
implements— implement one or more interfaces - →
super— access parent class constructor or methods - →
@Override— marks a method that overrides a parent method - →
final— on a class: cannot be subclassed; on a method: cannot be overridden - →
abstract— class cannot be instantiated; method must be overridden
What is Inherited:
- →Public and protected fields and methods
- →Package-private members (if same package)
What is NOT Inherited:
- →Private members
- →Constructors (but you can call them with super())
- →Static members (they belong to the class, not instances)
🎯 Why Do We Need It?
Inheritance solves code reuse in hierarchical relationships:
- →Is-a relationship — Dog IS-A Animal; SavingsAccount IS-A BankAccount
- →Code reuse — common behavior defined once in parent, inherited by all children
- →Polymorphism — treat subclasses uniformly through parent type reference
- →Framework extension — Spring, Hibernate, and most frameworks use inheritance for customization
However, inheritance is often overused. The modern rule: prefer composition over inheritance unless there is a clear IS-A relationship.
🏗️ What Happens in Real Projects?
In enterprise Spring Boot projects:
// Base entity with common audit fields
@MappedSuperclass
public abstract class BaseEntity {
@Id @GeneratedValue
private Long id;
@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
}
// All entities inherit audit fields
@Entity
public class Order extends BaseEntity { ... }
@Entity
public class Product extends BaseEntity { ... }This is a legitimate use of inheritance — all entities genuinely share audit behavior.
⚙️ How It Works
Constructor Chaining:
When you create a subclass object, the parent constructor runs first. If you don't call super() explicitly, Java calls the no-arg parent constructor automatically. If the parent has no no-arg constructor, you MUST call super(args) explicitly.
Method Resolution (Dynamic Dispatch):
At runtime, the JVM calls the most specific override. Even if the reference type is Animal, if the actual object is a Dog, Dog's method is called.
Method Hiding (static methods):
Static methods are NOT polymorphic. If a subclass defines a static method with the same signature, it hides the parent's static method — it does not override it.
Sealed Classes (Java 17+):
sealed class Shape permits Circle, Rectangle, Triangle
Restricts which classes can extend Shape — useful for exhaustive pattern matching.
💻 Example
Inheritance in an Enterprise Payment System — A payment system showing when inheritance is appropriate and when to use composition.
🤔 Common Confusions
❓ When should I use inheritance vs composition?
Use inheritance for IS-A relationships where the subclass is genuinely a specialized version of the parent (Dog IS-A Animal, SavingsAccount IS-A BankAccount). Use composition for HAS-A relationships (Car HAS-A Engine). The rule of thumb: if you cannot say "SubClass IS-A ParentClass" naturally, use composition. Composition is more flexible and avoids tight coupling.
❓ What is the difference between method overriding and method hiding?
Overriding applies to instance methods — the most specific implementation is called based on the actual runtime type (polymorphism). Hiding applies to static methods — the method called depends on the declared reference type, not the runtime type. Static methods are not polymorphic. Always annotate overrides with @Override to catch mistakes.
❓ Why does Java not support multiple inheritance for classes?
Multiple class inheritance creates the "diamond problem" — if class C extends A and B, and both A and B define the same method, which one does C inherit? Java avoids this by allowing only single class inheritance. Multiple interface inheritance is allowed because interfaces (before default methods) had no implementation to conflict.
🚨 Common Production Issues
Deep inheritance hierarchies — more than 2-3 levels deep becomes hard to understand and maintain. Prefer composition.
Calling overridable methods in constructors — if a parent constructor calls a method overridden by a subclass, the subclass method runs before the subclass constructor finishes, potentially accessing uninitialized fields.
Breaking Liskov Substitution Principle — a subclass that throws exceptions or weakens behavior where the parent did not violates LSP and breaks polymorphic code.
✅ Best Practices
Prefer composition over inheritance — use inheritance only for clear IS-A relationships.
Always annotate overriding methods with @Override — the compiler catches mistakes.
Never call overridable methods from constructors.
Design for inheritance or prohibit it — mark classes final if not intended for subclassing.
Keep inheritance hierarchies shallow — 2 levels max in most cases.
Use abstract classes to define template methods; use interfaces to define contracts.
🏛️ Architect's Note
In modern Spring Boot applications, inheritance is used sparingly: @MappedSuperclass for audit fields, abstract base controllers for shared error handling, and occasionally for strategy patterns. The dominant pattern is composition via dependency injection — services depend on interfaces, not concrete classes. This is more testable, more flexible, and avoids inheritance pitfalls.
💬 Frequently Asked Questions
🎯 Key Takeaways
🔗 Related Topics
🎯 Practice this topic in interviews
Core Java Interview Prep
Practice interview questions that connect directly to this technology track.
↗ Where this topic fits
Core Java Technology Guide
Return to the Core Java learning hub.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Sources
Sources / References
Use these Core Java references to verify the concept in official docs and continue into the most relevant SplashRide pages.
Official documentation
Related SplashRide pages
SplashRide Core Java learning path
Browse the full Core Java topic collection and learning order on SplashRide.
Core Java Interview Prep
Practice Core Java interview questions and scenario-based answers.
Backend Engineer Career Path
A structured journey through Core Java, Spring Boot, production backend engineering, and interview preparation.
Full Stack Java Developer Career Path
A guided route through frontend foundations, Java backend engineering, delivery workflows, and interview readiness.
Java Polymorphism: Overloading, Overriding, and Dynamic Dispatch
Learn Java polymorphism with runnable examples of overriding and overloading, declared versus runtime types, null overloads, static hiding, and interface contracts.
Abstraction
How abstract classes and interfaces define contracts in Java — when to use each, default methods, and how abstraction enables the SOLID principles.