Inheritance in Java

By the Syncfusion DevTutorials team · Last updated

Reuse code with inheritance: parent and child classes, the IS-A test, types of inheritance, extends, super and constructor chaining.

Think about a family.

A child gets many things from their parents: the family name, maybe eye colour, maybe a way of speaking. The child does not have to invent those traits from scratch. They come with the family.

But the child is also their own person. They learn new skills, and sometimes they do things differently from their parents.

In Java, a class can get fields and methods from another class in the same way. This is called inheritance.

In simple words: inheritance lets a new class reuse an existing class's code, then add to it or change it.

What You Will Learn

In this lesson, you will learn:

  1. What inheritance is, and the IS-A test for when to use it.
  2. What parent (superclass) and child (subclass) classes are.
  3. The types of inheritance Java supports.
  4. How to use the extends keyword.
  5. How the super keyword reaches the parent's methods and constructor.
  6. How constructors run from parent to child.
  7. How inheritance hierarchies are organised.

Start With a Working Example

Press Run.

Two child classes reuse the parent's code

public class Main {
    public static void main(String[] args) {
        Car car = new Car("Maruti", 5);
        Bike bike = new Bike("Hero", true);

        car.start();
        car.showSeats();

        bike.start();
        bike.showGear();
    }
}

class Vehicle {
    String brand;

    Vehicle(String brand) {
        this.brand = brand;
    }

    void start() {
        System.out.println(brand + " is starting.");
    }
}

class Car extends Vehicle {
    int seats;

    Car(String brand, int seats) {
        super(brand);
        this.seats = seats;
    }

    void showSeats() {
        System.out.println(brand + " car has " + seats + " seats.");
    }
}

class Bike extends Vehicle {
    boolean hasGears;

    Bike(String brand, boolean hasGears) {
        super(brand);
        this.hasGears = hasGears;
    }

    void showGear() {
        System.out.println(brand + " bike has gears: " + hasGears);
    }
}

Expected output:

Maruti is starting.
Maruti car has 5 seats.
Hero is starting.
Hero bike has gears: true

start() and brand are written once, in Vehicle. Car and Bike both get them for free. Each child then adds its own extra field and method.

Try This

Add a method void honk() to Vehicle that prints brand + " says beep!". Call car.honk() and bike.honk(). Both work, and you wrote honk() only once.

Introduction to Inheritance

Inheritance means one class receives the fields and methods of another class.

Without inheritance, Car, Bike and Bus would each need their own copy of brand and start(). Fixing a bug in start() would mean fixing it in three places.

With inheritance, the shared code lives in one parent class. Each child class only adds what makes it different.

The benefits:

  • Less repeated code. Shared fields and methods are written once.
  • Easier fixes. A change in the parent reaches every child.
  • Clear structure. The classes form a family tree that matches the real world.

IS-A Relationship

Before using inheritance, ask one question: "Is the child a kind of the parent?"

  • A car is a vehicle. ✓
  • A dog is an animal. ✓
  • A savings account is a bank account. ✓
  • A car is an engine? ✗ A car has an engine.

If the IS-A sentence makes sense, inheritance fits. This is called the IS-A relationship.

If the sentence only works as "has a", use a field instead. A Car should have an Engine field, not extend Engine. This is called the HAS-A relationship, or composition.

RelationshipTest sentenceJava toolExample
IS-A"A car is a vehicle"Inheritance (extends)class Car extends Vehicle
HAS-A"A car has an engine"A fieldclass Car { Engine engine; }

Parent and Child Classes

Parent Class (Superclass)

The parent class is the class being inherited from. It is also called the superclass or base class.

It holds the fields and methods that all its children share.

Child Class (Subclass)

The child class is the class that inherits. It is also called the subclass or derived class.

It gets the parent's members, and it can:

  • add new fields and methods;
  • override (replace) a parent method with its own version.

Relationship Between Classes

The child knows about its parent. The parent does not know about its children.

So a Car can use everything a Vehicle has. But a Vehicle cannot use seats, because not every vehicle has seats.

Reusing Existing Members

A child class inherits:

  • public and protected fields and methods;
  • default (no modifier) members, if the child is in the same package.

A child class does not inherit:

  • private members. They exist inside the object, but the child cannot reach them directly by name;
  • constructors. Each class has its own constructors. A child calls the parent's constructor with super(...).

The child reuses, adds and replaces

public class Main {
    public static void main(String[] args) {
        Employee e = new Employee();
        Manager m = new Manager();

        e.work();
        m.work();
        m.holdMeeting();

        System.out.println("Manager's company: " + m.company);
    }
}

class Employee {
    String company = "Syntech";

    void work() {
        System.out.println("Employee is writing reports.");
    }
}

class Manager extends Employee {
    void work() {
        System.out.println("Manager is reviewing reports.");
    }

    void holdMeeting() {
        System.out.println("Manager is holding a meeting.");
    }
}

Expected output:

Employee is writing reports.
Manager is reviewing reports.
Manager is holding a meeting.
Manager's company: Syntech

Manager reuses company without writing it. It replaces work() with its own version. It adds holdMeeting(), which a plain Employee does not have.

Types of Inheritance

Single

Single inheritance means one child extends one parent.

Animal
  └── Dog

Multilevel

Multilevel inheritance is a chain. A child becomes the parent of another class.

Animal
  └── Dog
        └── Puppy

A Puppy gets everything from Dog, and Dog gets everything from Animal. So Puppy has the members of both.

Hierarchical

Hierarchical inheritance means several children extend the same parent.

        Vehicle
       /   |    \
    Car   Bike   Bus

The first example in this lesson was hierarchical: Car and Bike both extend Vehicle.

Multilevel: each level adds one more ability

public class Main {
    public static void main(String[] args) {
        Puppy p = new Puppy();
        p.eat();
        p.bark();
        p.play();
    }
}

class Animal {
    void eat() {
        System.out.println("Eating food.");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("Barking: Woof!");
    }
}

class Puppy extends Dog {
    void play() {
        System.out.println("Playing with a ball.");
    }
}

Expected output:

Eating food.
Barking: Woof!
Playing with a ball.

Puppy wrote only play(). It got bark() from Dog and eat() from Animal, two levels up.

Multiple Inheritance Through Interfaces

Multiple inheritance means one class has more than one parent.

Java does not allow a class to extend two classes. class C extends A, B does not compile.

The reason is the diamond problem. If A and B both had a method show() with different bodies, which one should C get? Java avoids that problem.

But a class can implement many interfaces. That is how Java gives one class several "parents" safely.

One parent class, two interfaces

public class Main {
    public static void main(String[] args) {
        Duck d = new Duck();
        d.breathe();
        d.fly();
        d.swim();
    }
}

class Bird {
    void breathe() {
        System.out.println("Breathing air.");
    }
}

interface Flyer {
    void fly();
}

interface Swimmer {
    void swim();
}

class Duck extends Bird implements Flyer, Swimmer {
    public void fly() {
        System.out.println("Flying over the lake.");
    }

    public void swim() {
        System.out.println("Swimming in the lake.");
    }
}

Expected output:

Breathing air.
Flying over the lake.
Swimming in the lake.

Duck extends one class, Bird, and implements two interfaces. extends always comes before implements.

Hybrid Inheritance Through Interfaces

Hybrid inheritance mixes two or more of the types above. For example, a class might be part of a multilevel chain and also implement several interfaces.

   Animal                Pet (interface)
     │                      │
    Dog ────────────────────┤
     │                      │
  GuideDog        Trainable (interface)

A multilevel chain mixed with interfaces

public class Main {
    public static void main(String[] args) {
        GuideDog g = new GuideDog("Bruno");
        g.eat();
        g.bark();
        g.cuddle();
        g.learn("Stop at the kerb");
        g.guide();
    }
}

interface Pet {
    void cuddle();
}

interface Trainable {
    void learn(String command);
}

class Animal {
    void eat() {
        System.out.println("Eating.");
    }
}

class Dog extends Animal implements Pet {
    String name;

    Dog(String name) {
        this.name = name;
    }

    void bark() {
        System.out.println(name + " barks.");
    }

    public void cuddle() {
        System.out.println(name + " wags its tail.");
    }
}

class GuideDog extends Dog implements Trainable {
    GuideDog(String name) {
        super(name);
    }

    public void learn(String command) {
        System.out.println(name + " learned: " + command);
    }

    void guide() {
        System.out.println(name + " is guiding safely.");
    }
}

Expected output:

Eating.
Bruno barks.
Bruno wags its tail.
Bruno learned: Stop at the kerb
Bruno is guiding safely.

GuideDog sits at the bottom of a chain (Animal → Dog → GuideDog). It also gets Pet through Dog, and adds Trainable itself.

TypeShapeAllowed with classes?
SingleA → BYes
MultilevelA → B → CYes
HierarchicalA → B, A → CYes
MultipleA, B → COnly through interfaces
HybridA mix of the aboveOnly when the "multiple" part uses interfaces

Every Java class has a parent, even when you write no extends. Java quietly makes it extend Object, the root of all classes. That is why every object has methods like toString() and equals().

extends Keyword

extends creates the parent-child link.

class Child extends Parent {
    // new fields and methods
}

Rules:

  • A class can extend only one class.
  • A class cannot extend a final class.
  • A class can extend a class and implement interfaces: class A extends B implements C, D.
  • An interface can extend other interfaces, even several: interface C extends A, B.

super Keyword

super refers to the parent class part of the current object. It has two main uses.

Calling a Parent Method

When a child replaces a parent method, it can still call the parent's version with super.methodName().

This lets the child add to the parent's behaviour instead of rewriting it.

Calling a Parent Constructor

super(...) calls the parent's constructor. It must be the first line of the child's constructor.

super reaches the parent's method and constructor

public class Main {
    public static void main(String[] args) {
        SavingsAccount s = new SavingsAccount("Asha", 10000, 4);
        s.showDetails();
    }
}

class BankAccount {
    String owner;
    int balance;

    BankAccount(String owner, int balance) {
        this.owner = owner;
        this.balance = balance;
    }

    void showDetails() {
        System.out.println("Owner: " + owner);
        System.out.println("Balance: " + balance);
    }
}

class SavingsAccount extends BankAccount {
    int interestRate;

    SavingsAccount(String owner, int balance, int interestRate) {
        super(owner, balance);
        this.interestRate = interestRate;
    }

    void showDetails() {
        super.showDetails();
        System.out.println("Interest rate: " + interestRate + "%");
    }
}

Expected output:

Owner: Asha
Balance: 10000
Interest rate: 4%

super(owner, balance) lets the parent set its own fields. The child then sets only its extra field.

super.showDetails() prints the parent's two lines. The child then adds one more line. Nothing was copied.

thissuper
Refers toThe current objectThe parent part of the current object
this.x / super.xThis class's fieldThe parent's field
this.m() / super.m()This class's version of mThe parent's version of m
this(...) / super(...)Another constructor in this classA constructor of the parent

Constructor Chaining

When you create a child object, the parent's constructor always runs first. Then the child's constructor runs.

This makes sense. The child is built on top of the parent, so the parent part must be ready first.

If a child constructor does not call super(...), Java quietly adds super(); as its first line. That calls the parent's no-argument constructor.

Constructors run from the top of the family down

public class Main {
    public static void main(String[] args) {
        new Grandchild();
    }
}

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

class Parent extends Grandparent {
    Parent() {
        System.out.println("2. Parent constructor");
    }
}

class Grandchild extends Parent {
    Grandchild() {
        System.out.println("3. Grandchild constructor");
    }
}

Expected output:

1. Grandparent constructor
2. Parent constructor
3. Grandchild constructor

None of these constructors writes super(). Java added it to each one. So the chain runs from the top class down to the bottom.

If the parent has only constructors with parameters, Java cannot add super(); for you. The child must call super(...) with the right values, or it does not compile.

The child must call the parent's constructor with values

public class Main {
    public static void main(String[] args) {
        new Student();
    }
}

class Person {
    String name;

    Person(String name) {
        this.name = name;
    }
}

class Student extends Person {
    Student() {
        System.out.println("Student created");
    }
}

The compiler reports constructor Person in class Person cannot be applied to given types. Java tried to call super(), but Person has no constructor without parameters. The fix is to add super("Unknown"); as the first line of Student().

Easy Way to Remember: this(...) calls a constructor in the same class. super(...) calls a constructor in the parent class. Either one must be the first line, so a constructor can use only one of them.

Inheritance Hierarchies

An inheritance hierarchy is the full family tree of related classes.

                 Object
                   │
                Employee
         ┌─────────┼──────────┐
     Manager    Engineer    Intern
                   │
            SeniorEngineer

General ideas go near the top. Specific details go near the bottom.

  • Employee holds what every employee has: a name, an ID and a salary.
  • Engineer adds a programming language.
  • SeniorEngineer adds a team to lead.

Tips for a healthy hierarchy:

  • Keep it shallow. Three or four levels is plenty. Deep trees are hard to follow.
  • Pass the IS-A test at every level. A senior engineer is an engineer, and an engineer is an employee.
  • Put shared code as high as it is truly shared. Do not put a field in the parent if only one child uses it.

Common mistakes

The following mistakes are common when using inheritance. Each row shows what you see, why it happens and how to fix it.

SymptomCauseFix
'{' expected after extends A, BTwo classes after extendsExtend one class, implement interfaces
cannot be applied to given types on a constructorJava's automatic super() has no matching parent constructorCall super(...) with the right values
call to super must be first statementsuper(...) came after other codeMove it to the first line
has private accessA child used a parent's private memberUse a protected member or a public method
cannot inherit from finalThe parent class is finalUse composition instead
Strange designs, like a car that is an engineInheritance used for HAS-AUse a field instead

What to Remember

  • Inheritance lets a child class reuse a parent's fields and methods, then add or replace behaviour.
  • Use it only when the IS-A test passes. Use a field for HAS-A.
  • A class extends one class. It can implement many interfaces, which gives multiple and hybrid inheritance.
  • super.method() calls the parent's version. super(...) calls the parent's constructor and must come first.
  • Parent constructors always run before child constructors, from the top of the hierarchy down.
  • Every class ultimately extends Object. Keep hierarchies shallow and general at the top.

Next: Polymorphism