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:
- What inheritance is, and the IS-A test for when to use it.
- What parent (superclass) and child (subclass) classes are.
- The types of inheritance Java supports.
- How to use the
extendskeyword. - How the
superkeyword reaches the parent's methods and constructor. - How constructors run from parent to child.
- 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.
| Relationship | Test sentence | Java tool | Example |
|---|---|---|---|
| IS-A | "A car is a vehicle" | Inheritance (extends) | class Car extends Vehicle |
| HAS-A | "A car has an engine" | A field | class 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:
publicandprotectedfields and methods;- default (no modifier) members, if the child is in the same package.
A child class does not inherit:
privatemembers. 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.
| Type | Shape | Allowed with classes? |
|---|---|---|
| Single | A → B | Yes |
| Multilevel | A → B → C | Yes |
| Hierarchical | A → B, A → C | Yes |
| Multiple | A, B → C | Only through interfaces |
| Hybrid | A mix of the above | Only 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
finalclass. - 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.
this | super | |
|---|---|---|
| Refers to | The current object | The parent part of the current object |
this.x / super.x | This class's field | The parent's field |
this.m() / super.m() | This class's version of m | The parent's version of m |
this(...) / super(...) | Another constructor in this class | A 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.
Employeeholds what every employee has: a name, an ID and a salary.Engineeradds a programming language.SeniorEngineeradds 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.
| Symptom | Cause | Fix |
|---|---|---|
'{' expected after extends A, B | Two classes after extends | Extend one class, implement interfaces |
cannot be applied to given types on a constructor | Java's automatic super() has no matching parent constructor | Call super(...) with the right values |
call to super must be first statement | super(...) came after other code | Move it to the first line |
has private access | A child used a parent's private member | Use a protected member or a public method |
cannot inherit from final | The parent class is final | Use composition instead |
| Strange designs, like a car that is an engine | Inheritance used for HAS-A | Use 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
extendsone class. It canimplementmany 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