JavaOOPbeginner
Updated:

Inheritance in Java with Real Examples

6 min read

Understand how the extends keyword, super, and method overriding work together, and learn when inheritance helps your design and when composition is the better call.

TL;DR – Quick Answer

Inheritance in Java lets one class (the subclass) reuse and extend the fields and methods of another class (the superclass) using the extends keyword. It models an is-a relationship: a Manager is an Employee. The subclass inherits non-private members, can add its own, and can override inherited methods to change behavior.

On This Page

Inheritance is the pillar of OOP that interviewers reach for first, because a wrong answer here exposes shaky fundamentals immediately. It is also the feature beginners misuse most often — extending classes just to reuse a method, then wondering why their design falls apart two weeks later.

This tutorial walks through inheritance the way we teach it in class: real code, the super keyword, overriding, and the honest answer to "should I even use inheritance here?" If you have not yet read the overview of all four OOP pillars, skim that first — this page goes deep on one pillar.

What inheritance actually means

Inheritance lets one class acquire the fields and methods of another. The class being extended is the superclass (parent), and the class doing the extending is the subclass (child). The keyword is extends.

The mental test is the is-a relationship. A Manager is an Employee. A SavingsAccount is a BankAccount. If you cannot say "X is a Y" out loud without it sounding wrong, inheritance is the wrong tool.

Two things a subclass gets to do:

  1. Reuse — every non-private field and method of the parent works on the child without rewriting it.
  2. Specialize — the child adds new members or overrides inherited methods to change behavior.

A real example: Employee and Manager

Here is a complete, runnable example. Notice that Manager never declares name, salary, or displayDetails(), yet uses all three.

class Employee {
    String name;
    double salary;

    Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    void displayDetails() {
        System.out.println(name + " earns " + salary);
    }
}

class Manager extends Employee {
    int teamSize;

    Manager(String name, double salary, int teamSize) {
        super(name, salary);   // must run the parent constructor first
        this.teamSize = teamSize;
    }

    void conductReview() {
        System.out.println(name + " is reviewing " + teamSize + " people");
    }
}

public class Main {
    public static void main(String[] args) {
        Manager m = new Manager("Anitha", 95000, 6);
        m.displayDetails();    // inherited from Employee
        m.conductReview();     // Manager's own method
    }
}

What to notice: Manager has access to name directly because the field has default (package) access. If Employee declared it private, Manager would need a getter — private members are present in the child object's memory but not accessible by name.

Common mistake: A common mistake beginners make is thinking private members are "not inherited at all." They exist inside every child object — the child just cannot touch them directly. That is exactly why encapsulation pairs private fields with public getters.

The super keyword and constructor chaining

super does three jobs:

Usage Meaning
super(args) Call a parent constructor (must be the first statement)
super.method() Call the parent's version of an overridden method
super.field Access a parent field hidden by a child field of the same name

Constructors are not inherited, but they chain. When you write new Manager(...), Java runs Object's constructor, then Employee's, then Manager's — top of the hierarchy downward. If you do not write super(...) yourself, the compiler inserts a call to the parent's no-argument constructor. If the parent has no no-arg constructor, your code will not compile until you call super(...) explicitly.

class Vehicle {
    Vehicle() {
        System.out.println("Vehicle constructor");
    }
}

class Car extends Vehicle {
    Car() {
        // compiler inserts super(); here
        System.out.println("Car constructor");
    }
}

public class ChainDemo {
    public static void main(String[] args) {
        new Car();
        // Output:
        // Vehicle constructor
        // Car constructor
    }
}

What to notice: the parent line prints first even though you only constructed a Car. Interviewers love asking you to predict this output.

Method overriding: changing inherited behavior

Overriding means the subclass provides its own body for a method it inherited, keeping the same signature. This is where inheritance connects to runtime polymorphism — the JVM picks the child's version even when the reference type is the parent.

class BankAccount {
    protected double balance = 10000;

    double withdrawalLimit() {
        return 25000;
    }
}

class SavingsAccount extends BankAccount {
    @Override
    double withdrawalLimit() {
        return 10000;   // savings accounts have a tighter limit
    }
}

public class OverrideDemo {
    public static void main(String[] args) {
        BankAccount acc = new SavingsAccount();  // parent reference, child object
        System.out.println(acc.withdrawalLimit()); // prints 10000.0
    }
}

What to notice: the reference type is BankAccount, yet the output is 10000.0 — the JVM dispatched to SavingsAccount's method at runtime.

Pro tip: Always write @Override above an overriding method. It costs nothing and turns a silent bug (typo in the method name creates a new method instead of overriding) into a compile error.

Rules to remember when overriding:

  • Same method name and parameter list; return type must be the same or a subtype (covariant return).
  • Access level cannot be more restrictive — you can widen protected to public, never narrow it.
  • You cannot override final, static, or private methods. Redefining a static method is called method hiding, and it resolves by reference type, not object type.

Types of inheritance Java supports

Type Shape Supported with classes?
Single A → B Yes
Multilevel A → B → C Yes
Hierarchical A → B, A → C Yes
Multiple A, B → C No (classes); yes via interfaces
Hybrid Mix of the above Only where interfaces carry the multiple part

Java forbids multiple inheritance of classes because of the diamond problem: if C extends A, B and both parents define show(), which one does C inherit? Rather than invent tie-breaking rules for state, the language designers banned it. Interfaces sidestep the issue because they historically carried no state — and when Java 8 default methods reintroduced a mild diamond, the compiler simply forces you to override the conflicting method. See abstraction in Java for how interfaces fill this gap.

What gets inherited — and what doesn't

Inherited:

  • public, protected, and (same-package) default fields and methods
  • Nested types declared in the parent

Not inherited:

  • Constructors (they chain, but each class declares its own)
  • private members (present in memory, not accessible)
  • static members are shared through the class, not truly inherited per-object

Every class you write silently extends java.lang.Object, which is why toString(), equals(), and hashCode() exist on everything you create.

Inheritance vs composition: the design decision

The most senior-sounding thing a fresher can say in an interview is "I'd prefer composition here." Composition means holding another object as a field and delegating to it, instead of extending its class.

// Composition: a Car HAS-AN engine, it is not a kind of engine
class Engine {
    void start() { System.out.println("Engine started"); }
}

class Car {
    private final Engine engine = new Engine();

    void start() {
        engine.start();   // delegate
        System.out.println("Car moving");
    }
}

Choose inheritance when the is-a test passes and you want callers to substitute the child anywhere the parent is expected. Choose composition when you just want to reuse behavior — it keeps the two classes independently changeable and avoids a fragile hierarchy where one parent edit breaks five children.

Interview note: "Why does Java favor composition over inheritance?" is a standard follow-up at product companies in Hyderabad. Anchor your answer on coupling: inheritance couples the child to the parent's implementation details; composition couples it only to a public API. Practice more variants on our Java OOP interview questions page.

Where to go next

Inheritance is the mechanism; polymorphism is the payoff. Read Polymorphism in Java next to see why "parent reference, child object" is the single most useful line in this article. If you want the full picture with mentor-led practice — inheritance hierarchies, design exercises, and interview drills — that is exactly what week three of our Java Full Stack course covers.

Frequently Asked Questions

What is inheritance in Java in simple words?
Inheritance lets a new class reuse the fields and methods of an existing class instead of rewriting them. The new class is called the subclass or child, the existing one is the superclass or parent, and you connect them with the extends keyword. The child can also add new members and override inherited methods.
Why does Java not support multiple inheritance of classes?
Java blocks a class from extending two classes to avoid the diamond problem, where two parents define the same method and the compiler cannot decide which version the child should inherit. Java offers interfaces as the alternative: a class can implement any number of interfaces, and since Java 8 interfaces can even carry default method implementations with clear conflict-resolution rules.
What is the difference between extends and implements?
extends creates an inheritance link between two classes or two interfaces, and a class can extend only one class. implements is used when a class promises to provide the behavior declared by an interface, and a class can implement many interfaces at once. A single class can do both: class A extends B implements C, D.
Are constructors inherited in Java?
No. Constructors belong to the class that declares them and are never inherited. However, every subclass constructor must call a superclass constructor, either explicitly with super(...) or implicitly, because the parent portion of the object must be initialized before the child portion.
Can we override private or static methods in Java?
No. Private methods are not visible to the subclass, so a method with the same signature in the child is simply a new, unrelated method. Static methods belong to the class rather than the object, so redefining one in a subclass hides the parent version instead of overriding it, and the version called depends on the reference type.
When should I use composition instead of inheritance?
Use inheritance only when the child genuinely is a type of the parent and you want polymorphic substitution. If you only want to reuse functionality, hold a reference to the other class as a field and delegate to it. Composition keeps classes loosely coupled and avoids fragile hierarchies that break when the parent changes.

Want to Build Your Career in Java Full Stack with AI?

Join CodeBegun and train with working industry engineers — Explore the Program

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 14 July 2026 LinkedIn
Chat with us