Inheritance Java Program: Complete Guide with Examples (2026)
Inheritance is one of the four fundamental Object-Oriented Programming (OOP) principles in Java. It allows a class to acquire the fields and methods of another class, promoting code reuse, maintainability, and extensibility.
In this guide, you'll learn:
- What inheritance is and why it matters
- The different types of inheritance in Java
- Single inheritance with a complete Java program
- Multilevel inheritance with a working example
- How the
extendskeyword works - Best practices for writing maintainable inheritance hierarchies
All examples are compatible with modern Java versions, including Java 17 and Java 21 LTS, and follow practices that remain relevant in 2026.
Executive Overview
Inheritance represents an "is-a" relationship between classes. Instead of writing duplicate code across multiple classes, developers define common functionality in a parent class and allow child classes to inherit and extend that functionality.
For example:
- A Dog is an Animal.
- A Car is a Vehicle.
- A SavingsAccount is a BankAccount.
Each child class automatically gains access to accessible members of its parent class while adding its own specialized behavior.
Inheritance offers several advantages:
- Reduces duplicate code
- Improves maintainability
- Encourages code reuse
- Supports runtime polymorphism
- Makes applications easier to extend
However, inheritance should be used only when a genuine "is-a" relationship exists. Modern Java development encourages developers to prefer composition when inheritance becomes deep or tightly coupled.
Java supports inheritance through the extends keyword for classes and implements for interfaces. Unlike some programming languages, Java intentionally does not allow multiple inheritance of classes to avoid ambiguity, though a class can implement multiple interfaces.
Understanding inheritance is essential because it appears frequently in Java interviews, enterprise applications, frameworks like Spring, Android development, and backend systems.
Prerequisites
Before working through these programs, you should be comfortable with:
- Basic Java syntax
- Classes and objects
- Methods
- Constructors
- Access modifiers (
public,protected,private) - Compiling and running Java programs
- Java Development Kit (JDK 17 or newer)
A basic understanding of Object-Oriented Programming concepts such as encapsulation and polymorphism will also be helpful.
What Is Inheritance in Java?
Inheritance is the mechanism by which one class acquires the properties and behavior of another class.
The existing class is called the:
- Parent class
- Superclass
- Base class
The new class is called the:
- Child class
- Subclass
- Derived class
The child class inherits accessible methods and fields from the parent class and can also define additional members of its own.
General syntax:
class Parent {
// fields and methods
}
class Child extends Parent {
// additional fields and methods
}
The extends keyword establishes the inheritance relationship.
For example:
class Animal {
void eat() {
System.out.println("Animal is eating");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Dog is barking");
}
}
Here:
Doginherits theeat()method.Dogadds its ownbark()method.- A
Dogobject can call both methods without duplicating code.
This reuse of behavior is the primary purpose of inheritance.
Types of Inheritance in Java
Java supports several inheritance models.
Single Inheritance
A child class inherits from exactly one parent class.
Animal
│
▼
Dog
This is the simplest and most commonly used inheritance model.
Multilevel Inheritance
A class inherits from another child class, forming a chain.
Animal
│
▼
Dog
│
▼
Puppy
Each level inherits the behavior of every class above it.
Hierarchical Inheritance
Multiple child classes inherit from the same parent.
Animal
/ \
Dog Cat
This is commonly used when several classes share common functionality.
Multiple Inheritance (via Interfaces)
Java does not support multiple inheritance of classes because it can lead to ambiguity, commonly known as the Diamond Problem.
Instead, Java allows a class to implement multiple interfaces safely.
This topic is covered later in this guide.
Single Inheritance
Single inheritance allows one child class to inherit the methods and fields of one parent class.
This is the foundation of inheritance in Java and is widely used across enterprise applications.
Example Program
class Animal {
void eat() {
System.out.println("Eating...");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Barking...");
}
}
public class SingleInheritance {
public static void main(String[] args) {
Dog dog = new Dog();
dog.bark();
dog.eat();
}
}
Output
Barking...
Eating...
Explanation
The program contains two classes.
The Animal class provides the common behavior:
void eat()
The Dog class extends Animal:
class Dog extends Animal
Since Dog inherits from Animal, every Dog object automatically has access to the eat() method.
When the program executes:
Dog dog = new Dog();
the object can call:
dog.bark();
because it belongs to Dog.
It can also call:
dog.eat();
because the method is inherited from Animal.
No duplicate implementation of eat() is required inside the Dog class.
This demonstrates one of the biggest advantages of inheritance—code reuse.
Instead of rewriting shared functionality in every class, common behavior is centralized in the parent class.
When to Use Single Inheritance
Single inheritance is ideal when:
- Multiple objects share common behavior.
- The child naturally extends the parent.
- Code duplication needs to be minimized.
- The hierarchy is simple and easy to maintain.
Examples include:
- Employee → Manager
- Vehicle → Car
- Account → SavingsAccount
- Shape → Circle
Multilevel Inheritance
Multilevel inheritance occurs when a child class itself becomes the parent of another class.
Each level inherits the accessible members of every class above it.
This creates a chain of inheritance.
Example Program
class Animal {
void eat() {
System.out.println("Eating...");
}
}
class Dog extends Animal {
void bark() {
System.out.println("Barking...");
}
}
class Puppy extends Dog {
void weep() {
System.out.println("Weeping...");
}
}
public class MultilevelInheritance {
public static void main(String[] args) {
Puppy puppy = new Puppy();
puppy.weep();
puppy.bark();
puppy.eat();
}
}
Output
Weeping...
Barking...
Eating...
Explanation
The inheritance chain is:
Animal
│
▼
Dog
│
▼
Puppy
The Animal class defines:
eat()
The Dog class inherits eat() and introduces:
bark()
Finally, the Puppy class inherits both methods and defines:
weep()
As a result, the Puppy object can invoke all three methods:
weep()fromPuppybark()fromDogeat()fromAnimal
This illustrates how inheritance accumulates functionality through each level of the hierarchy.
Advantages of Multilevel Inheritance
Multilevel inheritance is useful when functionality becomes progressively more specialized.
Its benefits include:
- Better organization of related classes
- Reduced code duplication
- Easier maintenance
- Incremental extension of functionality
- Improved readability for well-designed hierarchies
However, avoid creating excessively deep inheritance chains. Modern Java design generally recommends keeping hierarchies shallow because deep inheritance can make applications more difficult to understand, debug, and modify. When classes become too tightly coupled, composition is often a better design choice.
Multiple Inheritance Using Interfaces
Unlike C++, Java does not allow a class to inherit from multiple classes. However, Java does allow a class to implement multiple interfaces, enabling a form of multiple inheritance without the ambiguity associated with multiple parent classes.
Interfaces define contracts that implementing classes must fulfill. Since Java 8, interfaces can also include default and static methods, making them even more powerful while preserving backward compatibility.
Example Program
interface Vehicle {
void vehicleType();
}
interface Color {
void colorType();
}
class Car implements Vehicle, Color {
@Override
public void vehicleType() {
System.out.println("Four-wheeler");
}
@Override
public void colorType() {
System.out.println("Red");
}
}
public class MultipleInheritance {
public static void main(String[] args) {
Car car = new Car();
car.vehicleType();
car.colorType();
}
}
Output
Four-wheeler
Red
Explanation
In this example:
Vehicledefines thevehicleType()contract.Colordefines thecolorType()contract.Carimplements both interfaces.
The class therefore gains two independent capabilities without inheriting implementation from multiple parent classes.
This approach is flexible because multiple interfaces can be combined as application requirements evolve.
Why Java Doesn't Support Multiple Class Inheritance
A common interview question is:
Why can't one Java class extend multiple classes?
The answer lies in avoiding ambiguity.
Consider the following hypothetical example:
class A {
void display() {
System.out.println("A");
}
}
class B {
void display() {
System.out.println("B");
}
}
// Not allowed in Java
class C extends A, B {
}
If C called:
display();
Which implementation should execute?
A.display()B.display()
This ambiguity is known as the Diamond Problem.
Rather than introducing complex conflict-resolution rules, Java avoids the problem entirely by allowing a class to extend only one superclass.
Interfaces solve this safely because they primarily define behavior contracts rather than shared implementation. If two interfaces contain identical default methods, Java requires the implementing class to explicitly override the conflicting method.
This design keeps inheritance predictable, readable, and easier to maintain.
extends vs implements
Both keywords establish relationships between types, but they serve different purposes.
Use extends when:
- Creating a child class from a parent class
- Reusing implementation
- Modeling an "is-a" relationship
- Inheriting fields and methods
Example:
class Animal {
}
class Dog extends Animal {
}
Use implements when:
- Implementing one or more interfaces
- Defining capabilities or contracts
- Allowing different classes to share behavior without sharing implementation
Example:
interface Printable {
void print();
}
class Report implements Printable {
@Override
public void print() {
System.out.println("Printing report");
}
}
As a design guideline:
- Use inheritance for closely related classes.
- Use interfaces for shared capabilities across unrelated classes.
Modern Java frameworks rely heavily on interfaces because they encourage loose coupling and easier testing.
Method Overriding and Runtime Polymorphism
Inheritance becomes significantly more useful when combined with method overriding.
A child class can provide its own implementation of an inherited method.
Example:
class Animal {
void sound() {
System.out.println("Some sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Bark");
}
}
Now consider:
Animal animal = new Dog();
animal.sound();
Output:
Bark
Although the reference type is Animal, Java executes the overridden method from Dog.
This behavior is called runtime polymorphism or dynamic method dispatch.
It allows applications to become more flexible because the same interface or parent type can represent many concrete implementations.
Many enterprise Java frameworks, including Spring, Jakarta EE, and numerous ORM libraries, rely heavily on runtime polymorphism.
The super Keyword
The super keyword refers to the immediate parent class.
It is commonly used for:
- Calling superclass constructors
- Accessing overridden methods
- Accessing hidden parent fields
Calling a Parent Constructor
class Animal {
Animal() {
System.out.println("Animal created");
}
}
class Dog extends Animal {
Dog() {
super();
System.out.println("Dog created");
}
}
Output:
Animal created
Dog created
If omitted, Java automatically inserts super() when possible.
Calling an Overridden Method
class Animal {
void sound() {
System.out.println("Animal sound");
}
}
class Dog extends Animal {
@Override
void sound() {
super.sound();
System.out.println("Dog bark");
}
}
Output:
Animal sound
Dog bark
Using super makes it possible to extend existing behavior rather than completely replacing it.
Real-World Use Cases
Inheritance is widely used across Java applications when there is a clear hierarchical relationship.
Examples include:
Banking Systems
Account
├── SavingsAccount
├── CurrentAccount
└── FixedDepositAccount
Each account type inherits common banking operations while implementing specialized functionality.
E-Commerce Applications
Product
├── Book
├── Laptop
└── MobilePhone
Shared attributes such as price and product ID are defined once in the parent class.
Human Resource Systems
Employee
├── Manager
├── Developer
└── Tester
All employees share common information while maintaining role-specific behavior.
GUI Frameworks
Desktop UI toolkits often define base components such as:
Component
├── Button
├── Label
└── TextField
Each component inherits rendering and event-handling functionality.
Game Development
Character
├── Warrior
├── Mage
└── Archer
Movement, health, and inventory logic can reside in the base class while subclasses define unique abilities.
Common Pitfalls & Edge Cases
Although inheritance is powerful, it can be misused.
Using Inheritance Instead of Composition
Not every relationship is an "is-a" relationship.
For example, a Car has an Engine; it is not an engine.
Favor composition when objects collaborate rather than specialize.
Deep Inheritance Chains
Hierarchies with many levels become difficult to understand and maintain.
For example:
A
└── B
└── C
└── D
└── E
Shallow hierarchies are generally easier to work with.
Forgetting @Override
Always annotate overridden methods.
The compiler can detect signature mismatches before runtime.
@Override
public void display() {
}
Access Modifier Confusion
Private members are not inherited directly.
Only accessible members (public, protected, and package-private within the same package) can be used by subclasses.
Incorrect Constructor Assumptions
Superclass constructors execute before subclass constructors.
Understanding constructor chaining helps avoid initialization bugs.
Confusing Overloading and Overriding
These concepts are frequently mixed up.
- Overloading: Same method name, different parameters.
- Overriding: Same method signature in a subclass.
They solve different design problems.
Best Practices (2026)
Modern Java development favors simplicity and maintainability over deep inheritance hierarchies.
Follow these recommendations:
- Prefer inheritance only for genuine "is-a" relationships.
- Keep inheritance trees shallow.
- Favor composition when classes collaborate.
- Use interfaces to define capabilities.
- Always use the
@Overrideannotation. - Avoid exposing unnecessary parent implementation details.
- Design parent classes to be stable and reusable.
- Use meaningful class names that reflect the domain model.
- Document inheritance hierarchies in larger projects.
- Follow the Liskov Substitution Principle so subclasses can safely replace their parent types.
When designing enterprise applications, prioritize readability and maintainability over clever inheritance structures.
Conclusion
Inheritance remains one of Java's most important object-oriented programming features because it enables code reuse, extensibility, and cleaner software design. By placing common behavior in a parent class and extending it through specialized subclasses, developers can build applications that are easier to maintain and evolve.
Java supports single, multilevel, and hierarchical inheritance through classes while intentionally preventing multiple class inheritance to eliminate ambiguity. Instead, multiple interfaces provide a flexible and safe mechanism for combining behaviors.
As you build larger Java applications, remember that inheritance is just one design tool. Use it thoughtfully, keep class hierarchies simple, and combine it with interfaces, composition, and polymorphism to create maintainable, scalable software.
Key Takeaways
- Inheritance models an "is-a" relationship between classes.
- The
extendskeyword enables class inheritance. - Java supports single, multilevel, and hierarchical inheritance.
- Multiple inheritance of classes is not supported, but multiple interfaces are.
- Method overriding enables runtime polymorphism.
- The
superkeyword provides access to parent constructors and methods. - Use inheritance to promote code reuse, but avoid unnecessarily deep hierarchies.
- Prefer composition when inheritance does not accurately represent the domain model.
- Modern Java applications often combine inheritance with interfaces to achieve flexibility and maintainability.
8 free, 100% client-side tools for developers — no signup, no data uploads.
Explore all tools