Override Method in Java Tutorial

  • Post author:
  • Post category:Java

In this section, we will learn what method overriding is and how it works in Java.

Note: before reading this section, we’re assuming you’re familiar with inheritance.

What is Method overriding and How to Override a Method in Java?

In programming, we usually design a class to inherit from another one, because in the base class there are members that we believe are useful in the child class as well.

Basically, we see the concept of `is-a` relationship between the two classes and so we decide to inherit from that class.

For example, a class named `Employee` can be the parent of another class named `Manager` because after all a manager is an employee. So the there’s a good chance (depending on how the class is designed) that the members inside the `Employee` are also applicable to the `Manager` class.

Sometimes there are methods in the parent class that the child class needs it but with a bit of modification inside the body of those methods.

This is where method overriding comes in. Basically, in the child class, we can override one or more methods of the base class and define another body with the same method name and signature (number and types of parameters) in the child class. So now, if we create an object from the child class, the instance will use the overridden method instead of using methods in the base class.

Example: Method overriding in Java

Create a class named `Employee` and put the code below into that class:

public class Employee {
    public void jobDescription(){
        System.out.println("Hi, I'm an employee :)");
    }
}

Now create another class named `Manager` and put the code below into that file:

public class Manager extends Employee{
}

Here the `Manager` class derived from the `Employee` and so it has the access to the non-private members of this class.

Now let’s create an object from the `Manager` class and call `jobDescription()` method via this object:

public class Simple {
    public static void main(String[] args) {
        Manager manager = new Manager();
        manager.jobDescription();
    }
}

Output:

Hi, I'm an employee 🙂

In this example, the message is sent to the output stream as expected. But wouldn’t it be more interesting if we could use this method for the `Manager` class with a different body?

For example, instead of sending the message `Hi, I’m an employee` we would like to see the message that says `Hi, I’m the manager of the company`.

This is where method overriding comes in.

Basically, we can choose a method of a parent class and override it inside the body of a sub-class.

Overriding means the target method is redefined in the sub-class with the same signature that it had in the parent class but with the different body.

Same signature means the same name, and the same number of type of parameter.

Let’s override the `jobDescription()` method of the `Employee` in the `Manager` class:

public class Manager extends Employee{
    @Override public void jobDescription(){
        System.out.println("Hi, I'm the manager of the company.");
    }
}

Now that we refactored the `Manager` class, let’s rerun the program to see what we’ll get this time in the output stream:

public class Simple {
    public static void main(String[] args) {
        Manager manager = new Manager();
        manager.jobDescription();
        Employee emp = new Employee();
        emp.jobDescription();
    }
}

Output:

Hi, I’m the manager of the company.

Hi, I’m an employee 🙂

As you can see when we call the `jobDescription()` via an object of type `Manager` we get a different message than calling the same method but via an object of the type `Employee` class.

Java `@Override` keyword

The `@Override` keyword is called annotation. In a later section we explained what annotations are, but for now just remember that when we override a method in a subclass, we use the `@Override` annotation before the target method in the subclass. This signals the compiler that the same method is used in the parent class and we’re overriding it. The compiler then check the parent class for this method and makes sure we’re properly overriding it (using the same name and parameter).

Note: the use of `@Override` annotation is optional, but it’s a good practice to use this before an overridden method. So we get the support of the compiler as well.

Java Method Overriding Notes:

  • The method must be a non-static and non-final method. Overriding does not apply to static methods.
  • The overriding method must have the same name as the overridden method.
  • The overriding method must have the same number of parameters of the same type in the same order as the overridden method.
  • The access level of the overriding method must be at least the same or more relaxed than that of the overridden method. The three access levels are public, protected and package-level that allow for inheritance. Recall that private members are not inherited and hence, cannot be overridden. The order of access level from the most relaxed to the strictest is public, protected, and package-level. If the overridden method has a public access level, the overriding method must have the public access level because public is the most relaxed access level. If the overridden method has a protected access level, the overriding method may have public or protected access level. If the overridden method has package-level access, the overriding method may have public, protected, or package-level access.
  • A method may include a list of checked exceptions in its throws clause. Although it is allowed to include an unchecked exception in the throw clause of a method, it is not required. In this section, I am discussing only checked exceptions. The overriding method cannot add a new exception to the list of exceptions in the overridden method. It may remove one or all exceptions or it may replace an exception with another exception, which is one of the descendants of the exception listed in the overridden method.
  • Before Java 5, the return type of the overriding and the overridden methods must be the same. In Java 5, this rule remains the same for return types of primitive data types. However, it has changed for return types of reference data types. If the return type of the overridden method is a reference type, the return type of the overriding method must be assignment-compatible with the return type of the overridden method. Suppose a class has a method definition of R1 m1(), which is overridden by a method definition R2 m1(). This method overriding is allowed only if an instance of R2 can be assigned to a variable of R1 type without any typecast.

Overriding Final Methods in Java

As mentioned before, we can’t override a final method! If we try so, the compiler will return an error.

Example: final method overridden in Java

package com.example.demo;

public class Parent{
    public final void saySomething(){
        System.out.println("My Parents are saying Hi :)");
    }
}


package com.example.demo;

public class Child extends Parent{
    @Override
    public void saySomething(){
        System.out.println("The child is saying Hi :)");
        super.saySomething();
    }
}

Output:

java: saySomething() in com.example.demo.Child cannot override saySomething() in com.example.demo.Parent

overridden method is final

If we run this example, we will get the error you see on the output, which is saying a final method cannot be overridden.

Override Static Methods in Java

As mentioned before, static methods cannot be overridden.

How to invoke overridden method from subclass? (super keyword and Method overriding)

We will talk about the `super` keyword in the Java super keyword section but in short, if you override a method in a child class but still insist in calling the same method in the parent class as well, then you can use the `super` keyword to invoke the same method in the parent class.

Basically, in the body of the method that you’ve overridden, call the `super` keyword + dot `.` + the name of the overridden method. This way, the execution engine will move through the chain of inheritance and will look for the closest class that contains the mentioned method in order to invoke it.

Note: calling the `super` keyword and then putting the name of a method can happen within the body of any other method in the child class! It doesn’t have to be only in the body of a method that has been overridden.

Example: invoking overridden method from sub-class

package com.example.demo;

public class Parent{
    public void saySomething(){
        System.out.println("My Parents are saying Hi :)");
    }
}


package com.example.demo;

public class Child extends Parent{
    @Override
    public void saySomething(){
        System.out.println("The child is saying Hi :)");
        super.saySomething();
    }
}


package com.example.demo;

public class Main {

    public static void main(String[] args) {
        Child child = new Child();
        child.saySomething();
    }
}

Output:

The child is saying Hi 🙂

My Parents are saying Hi 🙂

Here, both the Child and Parent classes have a method called `saySomthing()`. Basically the child class overrode this method.

So now if we create an instance from the Child class and call the `saySomething()` method, then only the method in the Child class will be called and the one in the Parent class will be ignored.

So in order to call the same method in the parent class as well, we can use the `super` keyword within the body of the `saySomething()` in the child class and that way the execution engine will move to the `Parent` class and runs the same method there too.

Is it possible to override a constructor in Java?

No! We can apply overloading to a constructor in Java but not overriding! Because there’s no way for the Java execution engine to find out which constructor function, it should run when a call to an overridden constructor happened.

Overriding vs Overloading in Java

In short, method overriding is about using the exact same signature of a method from a parent class in a child class but with a different body! Also, overriding comes in when a class inherits from another class.

On the other hand, when it comes to overloading, only the name of involved methods are the same, but other than the name, their signatures are different. Overloading can happen even when a class does not inherit from another class.

Reference book:

Beginning Java 9 Fundamentals, 2nd Edition.

Written by: Kishori Sharan

Leave a Reply