Java Inheritance

Summary: in this tutorial, you will learn about Java inheritance and how to utilize it to create a class that inherits the fields and methods from an existing class.

Introduction to Java inheritance

Inheritance allows you to define a new class based on an existing class. The new class will inherit the fields and methods of the existing class.

To define a class that inherits from an existing class, you use the extends keyword:

class Superclass{
   // ...
}
class Subclass extends Superclass {
  // ...
}Code language: Java (java)

In this syntax, the subclass inherits the fields and method of the superclass. The subclass may also have its own fields and methods.

The subclass and superclass are also known as the derived class and base class respectively.

The relationship between the subclass and superclass is an “is-a” relationship.

Java allows a class to inherit from a single class, which is referenced to as a single inheritance. It doesn’t support multiple inheritance, where a class can inherit from multiple classes.

Java inheritance example

Suppose you have an existing class called Person as follows:

// Person.java
class Person {
    public String name;

    public String sayHi() {
        return String.format("Hi, I'm %s. ", name);
    }
}Code language: Java (java)

The Person class has a public field name and a method sayHi().

The following shows how to define an Employee class that extends the Person class:

// Employee.java
class Employee extends Person {

}Code language: Java (java)

Because the Employee class inherits from the Person class, it is a Person class. It means that you can use the Employee class like a Person class.

For example, you can create a new Employee object, set the name, and call the sayHi method:

// App.java
public class App {
    public static void main(String[] args) {
        var e = new Employee();
        e.name = "John";
        System.out.println(e.sayHi());
    }
}Code language: Java (java)

Output:

Hi, I'm John.Code language: Java (java)

In this example, the Employee class doesn’t contain any specific code. But it can reuse the code from the Person class.

protected access modifier

In the Person class, the name field is a public field that can be accessible from any part of the application including the Employee class.

The following changes the access modifier of the name field from public to private:

class Person {
    private String name;

    public String sayHi() {
        return String.format("Hi, I'm %s. ", name);
    }
}Code language: Java (java)

Because of the private access modifier, the name field is not accessible outside of the Person class anymore. Therefore, the following code will not compile:

public class App {
    public static void main(String[] args) {
        var e = new Employee();
        e.name = "John"; // error
        System.out.println(e.sayHi());
    }
}Code language: Java (java)

To allow a subclass to access the fields and methods of the superclass, you need to use the protected access modifier.

For example, the following changes the access modifier of the name field in the Person class to protected:

class Person {
    protected String name;

    public void sayHi() {
        return String.format("Hi, I'm %s. ", name);
    }
}Code language: Java (java)

Now, the Employee class can access the name field.

Adding fields to subclass

Besides fields and methods inherited from the Person class, the Employee class can have its own fields and methods.

For example, the following add the job title field to the Employee class:

class Employee extends Person {
    public String jobTitle;
}Code language: Java (java)

The Employee class now has two fields:

  • name: This field is inherited from the Person class.
  • jobTitle: This is its own field.

The following shows how to create an instance of the Employee class, assign values to the name and jobTitle fields, and call the sayHi() method:

public class App {
    public static void main(String[] args) {
        var e = new Employee();
        e.name = "John";
        e.jobTitle = "Java Developer";
        System.out.println(e.sayHi());
    }
}Code language: Java (java)

Output:

Hi, I'm John.Code language: Java (java)

The sayHi() method shows only the name. What if we want to display the job title? To do that we can override the sayHi() method in the Employee class.

Overriding methods

Method overriding allows a subclass to provide a specific implementation for a method defined in its superclass.

To override a method, you use the same method signature of the method in the superclass.

For example, the following illustrates how to define the sayHi() method in the Employee class that overrides the sayHi() method in the Person class:

class Employee extends Person {
    public String jobTitle;

    public String sayHi() {
        return String.format("Hi, I'm %s. I'm a %s.",
                name,
                jobTitle
        );
    }
}Code language: Java (java)

If you call the sayHi() method using the Employee object, the sayHi() method in the Employee class will execute instead of the one defined in the Person class:

public class App {
    public static void main(String[] args) {
        var e = new Employee();
        e.name = "John";
        e.jobTitle = "Java Developer";

        System.out.println(e.sayHi());
    }
}Code language: Java (java)

Output:

Hi, I'm John. I'm a Java Developer.Code language: Java (java)

When overriding a method, you use the @Override annotation to explicitly tell the Java compiler your intent:

class Employee extends Person {
    public String jobTitle;

    @Override
    public String sayHi() {
        return String.format(
                "%sI'm a %s.",
                super.sayHi(),
                jobTitle
        );
    }
}Code language: Java (java)

The Java compiler will issue an error if you use @Override but use a different method signature from the parent class.

For example, if you add a parameter to the sayHi() method and attempt to build it, you’ll get an error:

class Employee extends Person {
    public String jobTitle;

    @Override
    public String sayHi(int volume) {
        return String.format(
                "%sI'm a %s.",
                super.sayHi(),
                jobTitle
        );
    }
}Code language: Java (java)

Error:

java: method does not override or implement a method from a supertypeCode language: Java (java)

Java super keyword

The super keyword allows you to access the members of the superclass within the subclass.

You can use the super keyword to access superclass fields, call the superclass methods, or invoke the superclass constructors.

Calling superclass method

For example, the following shows how to use the super keyword to call the sayHi() method of the Person class in the sayHi() method of the Employee class:

class Employee extends Person {
    private String jobTitle;

    @Override
    public String sayHi() {
        return String.format(
                "%sI'm a %s.",
                super.sayHi(),
                jobTitle
        );
    }
}Code language: Java (java)

The program shows the same output as before. But the sayHi() method in the Employee can reuse the logic implemented by the sayHi() method of the Person class.

Invoking the superclass constructor

When you define a subclass, it automatically inherits all the constructors of the superclass. To call a constructor of a superclass, you use the super() keyword. For example:

First, add a constructor that accepts a parameter name to the Person class:

class Person {
    protected String name;

    public Person(String name){
        this.name = name;
    }
    
    public String sayHi() {
        return String.format("Hi, I'm %s. ", name);
    }
}Code language: Java (java)

Second, change the jobTitle field in the Employee class to private and add a constructor to the Employee class that accepts two parameters name and jobTitle:

class Employee extends Person {
    private String jobTitle;

    public Employee(String name, String jobTitle) {
        super(name);
        this.jobTitle = jobTitle;
    }

    @Override
    public String sayHi() {
        return String.format(
                "%sI'm a %s.",
                super.sayHi(),
                jobTitle
        );
    }
}Code language: Java (java)

In the Employee constructor, we use the super to call the Person constructor and assign the jobTitle argument to the jobTitle field.

Third, modify the program to create a new instance of Employee using the name and jobTitle arguments:

public class App {
    public static void main(String[] args) {
        var e = new Employee("John", "Java Developer");
        System.out.println(e.sayHi());
    }
}Code language: Java (java)

Output:

Hi, I'm John. I'm a Java DeveloperCode language: Java (java)

Summary

  • Java inheritance allows a subclass to inherit the properties and behaviors of a superclass.
  • Use the extends keyword to define a subclass.
  • Use the protected access modifier to allow the subclass to access fields and methods of the superclass.
  • A subclass can override a method in the superclass by providing a specific implementation.
  • Use the super keyword to access superclass fields, call superclass methods, or invoke superclass constructors in the subclass.