00:00

Inheritance in Java – Types, Rules and Examples

Last updated: 7 min read

Inheritance is the OOP mechanism by which one class acquires the fields and methods of another. The class that is inherited from is the superclass (parent, base class); the class that inherits is the subclass (child, derived class). In Java, a class inherits with the extends keyword, forming an IS-A relationship: a Manager is an Employee.

Inheritance enables code reuse and is the foundation of runtime polymorphism. This tutorial covers the syntax, what is and is not inherited, the types of inheritance, why Java has no multiple class inheritance, constructor order, and when to prefer composition.

1. Syntax and a First Example

Syntax
class SubClass extends SuperClass {
    // inherits SuperClass's accessible fields and methods
    // can add new members and override inherited methods
}
InheritanceBasics.java
public class InheritanceBasics {
    static class Employee {                         // superclass (parent)
        protected final String name;
        protected final double salary;

        Employee(String name, double salary) {
            this.name = name;
            this.salary = salary;
        }
        double annualPay() { return salary * 12; }
        String describe() { return name + " earns " + annualPay() + " per year"; }
    }

    static class Manager extends Employee {         // subclass (child) IS-A Employee
        private final double bonus;

        Manager(String name, double salary, double bonus) {
            super(name, salary);                    // initialise the inherited part first
            this.bonus = bonus;
        }
        @Override double annualPay() { return super.annualPay() + bonus; }   // specialise
        void approveLeave(String who) { System.out.println(name + " approved leave for " + who); }  // add
    }

    public static void main(String[] args) {
        Employee dev = new Employee("Ravi", 80_000);
        Manager mgr = new Manager("Asha", 120_000, 200_000);

        System.out.println(dev.describe());
        System.out.println(mgr.describe());   // describe() inherited, annualPay() overridden
        mgr.approveLeave("Ravi");
        System.out.println("Manager is an Employee? " + (mgr instanceof Employee));
    }
}
Output
Ravi earns 960000.0 per year
Asha earns 1640000.0 per year
Asha approved leave for Ravi
Manager is an Employee? true

A subclass can do three things with what it inherits: use it as is (describe()), override it (annualPay()), and add new members (approveLeave()).

2. What Is and Is Not Inherited

WhatIsInherited.java
public class WhatIsInherited {
    static class Parent {
        public    String pub  = "public";
        protected String prot = "protected";
                  String pkg  = "package-private";
        private   String priv = "private";
        String getPriv() { return priv; }   // private data reachable via inherited method
        static String util() { return "static method"; }
    }
    static class Child extends Parent {
        void show() {
            System.out.println(pub + ", " + prot + ", " + pkg);
            // System.out.println(priv);      // compile error: priv has private access
            System.out.println("via getter: " + getPriv());
            System.out.println("static: " + util());
        }
    }

    public static void main(String[] args) {
        new Child().show();
        System.out.println("Every class extends Object: " + new Child().getClass().getSuperclass().getSuperclass().getSimpleName());
    }
}
Output
public, protected, package-private
via getter: private
static: static method
Every class extends Object: Object
MemberInherited?
public and protected fields and methodsYes
Package-private membersOnly by subclasses in the same package
private membersNo (they exist in the object but are accessible only through inherited methods)
ConstructorsNo; called with super(...)
Static membersAccessible through the subclass, but belong to the parent; not overridden

Every class without an extends clause implicitly extends java.lang.Object, so every object has toString(), equals(), hashCode() and the other Object methods.

3. Types of Inheritance

Single inheritance

Single inheritance in Java: class B extends class A

One class extends one other class: Car extends Vehicle.

Multilevel inheritance

Multilevel inheritance in Java: C extends B extends A

A chain of inheritance: SportsCar extends Car, which extends Vehicle.

Hierarchical inheritance

Hierarchical inheritance in Java: several classes extend one parent

Several classes extend the same parent: Car and Truck both extend Vehicle.

InheritanceTypes.java
public class InheritanceTypes {
    // Single: B extends A
    static class Vehicle { String move() { return "moves"; } }
    static class Car extends Vehicle { String honk() { return "honks"; } }

    // Multilevel: C extends B extends A
    static class SportsCar extends Car { String turbo() { return "uses turbo"; } }

    // Hierarchical: several classes extend the same parent
    static class Truck extends Vehicle { String load() { return "carries cargo"; } }

    // "Multiple" via interfaces: one class, many interfaces
    interface Electric { default String charge() { return "charges"; } }
    interface Autonomous { default String drive() { return "drives itself"; } }
    static class RoboTaxi extends Car implements Electric, Autonomous { }

    public static void main(String[] args) {
        SportsCar s = new SportsCar();
        System.out.println("SportsCar " + s.move() + ", " + s.honk() + ", " + s.turbo());
        System.out.println("Truck " + new Truck().move() + " and " + new Truck().load());
        RoboTaxi r = new RoboTaxi();
        System.out.println("RoboTaxi " + r.move() + ", " + r.charge() + ", " + r.drive());
    }
}
Output
SportsCar moves, honks, uses turbo
Truck moves and carries cargo
RoboTaxi moves, charges, drives itself

4. Why Java Has No Multiple Class Inheritance

Multiple inheritance of classes is not supported in Java

A class cannot extend two classes (class C extends A, B does not compile). If both parents had a method or field with the same name, which one should C inherit? This ambiguity is the diamond problem, and Java avoids it for classes, which carry state.

Hybrid inheritance in Java achieved with interfaces

Multiple and hybrid inheritance are achieved with interfaces instead: a class can extend one class and implement many interfaces, as RoboTaxi does above. If two interfaces provide conflicting default methods, the class must override the method, as explained in Default Methods.

5. Constructors and super

Constructors are not inherited, but creating a subclass object always runs the parent constructors first, from the top of the hierarchy down:

ConstructorOrder.java
public class ConstructorOrder {
    static class A { A() { System.out.println("1. A constructor"); } }
    static class B extends A { B() { System.out.println("2. B constructor"); } }
    static class C extends B { C() { System.out.println("3. C constructor"); } }

    public static void main(String[] args) {
        new C();   // parent constructors always run first, top-down
    }
}
Output
1. A constructor
2. B constructor
3. C constructor

If a constructor does not call super(...) explicitly, the compiler inserts super(). If the parent has no no-argument constructor, the subclass must call one of its constructors explicitly. See super keyword and Constructor Chaining.

6. Controlling Inheritance

  • final class: cannot be extended (String, Integer).
  • final method: can be inherited but not overridden.
  • sealed class (Java 17): only the classes listed in permits can extend it.
  • Private constructor: prevents subclassing from outside the class.

7. Inheritance vs Composition

Inheritance couples the subclass tightly to the parent's implementation, and the subclass inherits everything, wanted or not. Use it only for a true IS-A relationship. For HAS-A relationships, use composition, holding another object as a field:

CompositionInstead.java
import java.util.ArrayList;
import java.util.List;

public class CompositionInstead {
    // Inheritance misuse: a Stack IS-NOT-A ArrayList, but it would inherit add(index), remove(index)...
    // Composition: a Stack HAS-A list and exposes only stack operations
    static class Stack<T> {
        private final List<T> items = new ArrayList<>();
        void push(T item) { items.add(item); }
        T pop() { return items.remove(items.size() - 1); }
        T peek() { return items.get(items.size() - 1); }
        boolean isEmpty() { return items.isEmpty(); }
    }

    public static void main(String[] args) {
        Stack<String> pages = new Stack<>();
        pages.push("home"); pages.push("java"); pages.push("inheritance");
        System.out.println("Back from: " + pages.pop());
        System.out.println("Now on:    " + pages.peek());
    }
}
Output
Back from: inheritance
Now on:    java

Had Stack extended ArrayList, callers could insert or remove elements in the middle and break the stack. (The JDK's old java.util.Stack extends Vector has exactly this flaw.) See Aggregation for HAS-A relationships.

8. Advantages and Disadvantages

AdvantagesDisadvantages
Code reuse: common code lives in the parentTight coupling: parent changes can break subclasses
Enables method overriding and polymorphismDeep hierarchies are hard to understand
Models natural IS-A hierarchiesSubclasses inherit members they may not want
Easier extension with new subclassesOnly one superclass per class

9. Summary

  • Inheritance lets a subclass reuse, override and extend a superclass using extends.
  • Private members and constructors are not inherited; every class ultimately extends Object.
  • Java supports single, multilevel and hierarchical inheritance of classes.
  • Multiple and hybrid inheritance are achieved through interfaces.
  • Parent constructors run first; prefer composition when the relationship is HAS-A.

Related Tutorials