Year End Sale: Get Upto 40% OFF on Live Training! Offer Ending in
D
H
M
S
Get Now
Overriding In Java

Overriding In Java

10 Sep 2024
Beginner
767 Views
36 min read
Learn with an interactive course and practical hands-on labs

Free Java Course With Certificate

Understanding Overriding in Java

Understanding Overriding in Java is a fundamental concept in Java's object-oriented programming. It allows a subclass to give a specific implementation of a method that is already specified in its parent class, which causes dynamic method dispatch. This guarantees the most relevant procedure is executed at runtime, hence increasing flexibility and code reuse.

In this Java Tutorial, we will look at What is Overriding in Java? And When to Apply Overriding in Java? We will also look at Rules for Java Method Overriding. So, let us start with "What is Overriding?".

Become a certified full stack developer with our expert-led Java Full Stack Developer Certification Training. Enroll today!

What is Overriding?

  • Overriding in Java allows a subclass to replace a method specified in its parent class with its variant.
  • This means that when you call the method on a subclass object, the subclass code of the method is used rather than the parent class code.
  • For example, Consider a Vehicle class having a StartEngine function. If your Car class extends Vehicle, it can override the startEngine function to start the engine in a way that is specific to vehicles.

What is Overriding?

Example of Method Overriding in Java

Consider a superclass called Vehicle and its subclass Car. The Vehicle class has a method called start(), which is overridden by the Car class to give a more particular implementation.

Example

class Vehicle {
    void start() {
        System.out.println("The vehicle starts");
    }
}

class Car extends Vehicle {
    @Override
    void start() {
        System.out.println("The car starts with a key");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Outputs: The car starts with a key
    }
}

Output

The car starts with a key

Explanation

In this example, the Car class overrides the start() method from the Vehicle class. When start() is called on a Vehicle reference pointing to a Car object, the overridden method in the Car class is executed, resulting in the output "The car starts with a key."

Why Overriding in Java is Useful?

  • Overridden methods in Java are a type of polymorphism that allows you to have a single method that can function differently depending on the object on which it is called.
  • One of the most significant advantages of object-oriented programming is the ability to reuse and strengthen code. Dynamic process execution allows you to utilize existing code libraries to call methods on new class objects without having to recompile your code while maintaining a clean and simple interface.
  • Overridden methods allow you to call a method on any object from a derived class without knowing the specifics of the modified superclass.

When to Apply Overriding in Java?

  • Identifying parent and child classes forms a hierarchy that helps make the most of polymorphism.
  • A well-designed parent class contains everything the child class needs to access directly and also outlines which methods the child class must implement on its own.
  • This setup allows the child class to use its own methods while maintaining a consistent interface.
  • By combining inheritance and overridden methods, the parent class defines the general structure of the methods that all its child classes will use.

Rules for Java Method Overriding

  1. The method name should be common and match that of the parent class.
  2. The method's signature (parameter list, return type) must be the same as the parent class.
  3. Classes must have an inheritance relationship between them.
  4. All abstract methods from the parent class should be overridden in the child class.
  5. If the methods are defined as static or final, they cannot be overridden.

Let's understand them with a simple examples:

1. Overriding and Access Modifiers

  • The access modifier for an overriding method can give more access but not less than the method it overrides.
  • For example, if a superclass has a protected method, the subclass can make it public but not private. Trying to make it private would cause a compile-time error.

Example

class Vehicle {
    public void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    @Override
    public void start() { // Must be public
        System.out.println("Car starts with a key");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Outputs: Car starts with a key
    }
}

Output

Car starts with a key

Explanation

  • The Vehicle class has a start() method which is public.
  • The Car class extends Vehicle and overrides the start() method, ensuring it is also public.
  • When the start()the method is invoked on a Carthe object referenced as a Vehicle, the overridden method in the Car class is executed, demonstrating polymorphism in Java.

2. Final methods can not be overridden

A method declared final cannot be overridden. The final keyword prevents the method's behavior from being modified in subclasses.

Example

class Vehicle {
    public final void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    // This would cause a compile-time error if uncommented
    // @Override
    // public void start() {
    //     System.out.println("Car starts with a key");
    // }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Outputs: Vehicle starts
    }
}

Output

Vehicle starts

Explanation

  • The Vehicle class has a start() method marked as final, which means it cannot be overridden by any subclasses.
  • In the Car class, attempting to override this method would result in a compile-time error.
  • When the start()a method is called on a Car object (referenced as a Vehicle), the start() method from the Vehicle class is executed, demonstrating that the final method cannot be overridden.

3. Static methods can not be overridden

Method hiding occurs when you define a static method with the same signature as another static method in the base class. The table below explains what occurs when you define a method with the same signature as one in a superclass.
Superclass Instance MethodSuperclass Static Method
Subclass Instance Method OverridesCauses a compile-time error
Subclass Static Method Causes a compile-time errorHides

Example

class Vehicle {
    public static void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    public static void start() { // Hides the Vehicle's start method
        System.out.println("Car starts with a key");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle.start(); // Outputs: Vehicle starts
        Car.start();     // Outputs: Car starts with a key
    }
}

Output

Vehicle starts
Car starts with a key

Explanation

  • The Vehiclethe class has a static start() method, which is hidden by the Car class’s static start() method. 
  • When Vehicle.start() is called, it invokes the start() method from the Vehicle class. Similarly, calling Car.start() invokes the start() method from the Car class.
  • This demonstrates method hiding in Java, where static methods are bound at compile time rather than runtime.

4. Private Methods Cannot Be Overridden

Private methods cannot be overridden since they are bonded at build time. We can't even override secret functions in a subclass. (For further information, please see this).

Example

class Vehicle {
    private void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    private void start() { // Not overriding
        System.out.println("Car starts with a key");
    }

    public void showStart() {
        start(); // Calls Car's private start method
    }
}

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car();
        myCar.showStart(); // Outputs: Car starts with a key
    }
}

Output

Car starts with a key

Explanation

  • The Vehicle class defines a private start() method, and the Car class defines its own private start() method. 
  • Since start() in Car is private, it does not override the start() method in Vehicle
  • The showStart() method in Car calls the private start() method defined in Car, so when showStart()is invoked, it prints, "Car starts with a key."

5. The Overriding Method Must Have the Same Return Type (or Subtype)

From Java 5.0 onwards, alternative return types can be used for an overriding method in the child class, but the child's return type must be a subtype of the parent's return type. This behavior is referred to as covariant return type.

Example

class Vehicle {
    public Vehicle start() {
        System.out.println("Vehicle starts");
        return new Vehicle();
    }
}

class Car extends Vehicle {
    @Override
    public Car start() { // Covariant return type
        System.out.println("Car starts with a key");
        return new Car();
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Outputs: Car starts with a key
    }
}

Output

Car starts with a key

Explanation

  • The Vehiclethe class has a method start() that returns a Vehicle instance.
  • The Carthe class overrides this method with a return type of Car, which is a subclass of Vehicle.
  • This is an example of covariant return types, where the overriding method can return a type that is a subtype of the return type of the method in the superclass.
  • When start() is called on a Vehicle reference pointing to a Car object, it executes the start() method from the Car class, resulting in "Car starts with a key" being printed.

6. Invoking Overridden Methods from Subclass

You can call an overridden method in the subclass using the super keyword, which refers to the superclass’s implementation.

Example

class Vehicle {
    public void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    @Override
    public void start() {
        super.start(); // Calls Vehicle's start
        System.out.println("Car starts with a key");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Outputs: Vehicle starts followed by Car starts with a key
    }
}

Output

Vehicle starts
Car starts with a key

Explanation

  • The Car class overrides the start() method from the Vehicle class.
  • Within the start() method in Car, it first calls super.start() to invoke the start() method of the superclass (Vehicle), which prints "Vehicle starts".
  • Then, it prints, "Car starts with a key."
  • When start() is called on a Vehicle reference pointing to a Car object, it prints both messages, with "Vehicle starts" followed by "Car starts with a key".

Overriding and Constructor

We cannot override the constructor because the parent and child classes cannot have the same constructor (the constructor name must always match the class name).
Overriding and Constructor

Example

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

class Car extends Vehicle {
    Car() {
        System.out.println("Car constructor");
    }
}

public class Main {
    public static void main(String[] args) {
        Car myCar = new Car(); // Outputs: Vehicle constructor followed by Car constructor
    }
}

Output

Vehicle constructor
Car constructor

Explanation

  • When creating an instance of the Car class, the constructor of its superclass (Vehicle) is invoked first before the constructor of the Car class.
  • This is because, in Java, the constructor of the superclass is always called before the subclass constructor.
  • As a result, "Vehicle constructor" is printed first, followed by "Car constructor."

Overriding and Exception Handling

When overriding methods, there are specific rules for handling exceptions.

Rule #1: Exception Types

The overriding method cannot throw broader checked exceptions than those specified in the superclass method. It can generate the same or narrower exceptions.

Example

import java.io.IOException;

class Vehicle {
    public void start() throws Exception {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    @Override
    public void start() throws IOException { // Narrower exception
        System.out.println("Car starts with a key");
    }
}

public class Main {
    public static void main(String[] args) {
        try {
            Vehicle myCar = new Car();
            myCar.start(); // Outputs: Car starts with a key
        } catch (Exception e) {
            System.out.println("Exception caught: " + e);
        }
    }
}

Output

Car starts with a key

Explanation

  • In this example, the Car class overrides the start() method of the Vehicle class.
  • The overriding method in Car throws a narrower exception type (IOException) compared to the method in Vehicle which throws a general Exception.
  • This is allowed in Java because a subclass method can only throw exceptions that are subclasses of the exceptions thrown by the superclass method.
  • When start() is called on a Vehicle reference pointing to a Car object, it executes the overridden method in Car, resulting in "Car starts with a key" being printed.

Rule #2: Exception Handling in Subclass

If the superclass method does not declare any checked exceptions, the subclass method cannot declare any checked exceptions.

Example

import java.io.IOException;

class Vehicle {
    public void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    @Override
    public void start() { // No checked exceptions allowed
        System.out.println("Car starts with a key");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Outputs: Car starts with a key
    }
}

Output

Car starts with a key

Explanation

  • In this example, the Car class overrides the start() method of the Vehicle class.
  • The overriding method in Car does not declare any checked exceptions, which is allowed as the superclass method does not throw any checked exceptions either.
  • When start() is called on a Vehicle reference pointing to a Car object, it executes the overridden method in Car, resulting in "Car starts with a key" being printed.

Overriding and Abstract Method

Abstract methods in a superclass must be overridden in concrete subclasses unless the subclass itself is abstract. This guarantees that all abstract methods are implemented.

Example

abstract class Vehicle {
    abstract void start();
}

class Car extends Vehicle {
    @Override
    void start() {
        System.out.println("Car starts with a key");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Outputs: Car starts with a key
    }
}

Output

Car starts with a key

Explanation

  • In this example, the Vehicle class is abstract and defines an abstract method start()
  • The Car class extends Vehicle and provides an implementation for the start() method. 
  • When start() is called on a Vehicle reference pointing to a Car object, it executes the overridden method in Car, resulting in "Car starts with a key" being printed.

Overriding and Synchronized/strictfp Method

Methods marked with synchronized or strictfp can be overridden, but these attributes will not be retained until explicitly expressed in the subclass.

Example

class Vehicle {
    public synchronized void start() {
        System.out.println("Vehicle starts");
    }
}

class Car extends Vehicle {
    @Override
    public void start() { // Not synchronized
        System.out.println("Car starts with a key");
    }
}

public class Main {
    public static void main(String[] args) {
        Vehicle myCar = new Car();
        myCar.start(); // Outputs: Car starts with a key
    }
}

Output

Car starts with a key

Explanation

  • In this example, the Vehiclethe class has a synchronized start() method, which ensures that only one thread can execute this method at a time.
  • However, the Car class overrides the start() method without the synchronized keyword.
  • When start() is called on a Vehicle reference pointing to a Car object, it executes the overridden method in Car, which is not synchronized.
  • Therefore, "Car starts with a key" is printed.

Method Overriding vs. Method Overloading

  • Overloading and Overriding are two basic ideas that are different in several various ways in Java.
  • Overloading is similar to a car's acceleration function, which can be utilized in a variety of ways.
  • For example, you can accelerate by pushing the gas pedal with varying degrees of force (the same procedure, different parameters).
  • The car's behavior changes depending on how you utilize the pedal.
  • Overriding is similar to a car's start function, in which different types of cars (for example, a petrol car and an electric car) have different ways to start, despite the fact that the operation is the same.
Method Overriding vs. Method Overloading
Overloading: Accelerating (int speed) results in varying actions based on the speed argument.
Overriding: start() results in different implementations for PetrolCar and ElectricCar, although having the same function signature.
Summary
In this Java tutorial, we looked at Method Overriding, a key feature of Java's object-oriented programming. Method overriding allows a subclass to provide a specific implementation of a method that has already been defined in the parent class. This provides dynamic method dispatch, ensuring that the most relevant method is executed at runtime, hence increasing flexibility and code reuse. To master concepts like these and advance your career, consider enrolling in ScholarHat's Full-Stack Java Developer Certification Training Course.

FAQs

Java's static and final methods cannot be overridden. Static methods are hidden and cannot be overridden since they are part of the class rather than an instance. Final methods are expressly designated as unchangeable, prohibiting any subclass from giving an alternative implementation.

Overriding methods in Java allows you to specify a specific implementation in a subclass that differs from the one in the parent class. This enables for dynamic method behavior, which promotes polymorphism and makes code more flexible and reusable.

If you do not override a method in a subclass, the method from the parent class is called by default. This can limit flexibility by preventing the subclass from providing its own specialized behavior, potentially leading to less adaptable code.

No, Java does not support overriding without inheritance. Method overriding requires a subclass to inherit a method from its parent class, letting the subclass implement the method itself. Without inheritance, there is no parent-child relationship to enable overriding.

Final methods cannot be overridden in Java. When a method is designated final, it cannot be modified or overridden by any subclass, ensuring that the original implementation is preserved.

The primary goal of method overriding in Java is to allow a subclass to offer a customized implementation of a method that is already defined in its parent class, allowing for dynamic method dispatch and ensuring that the most appropriate method is used at runtime.
Share Article
About Author
Shailendra Chauhan (Microsoft MVP, Founder & CEO at ScholarHat)

Shailendra Chauhan, Founder and CEO of ScholarHat by DotNetTricks, is a renowned expert in System Design, Software Architecture, Azure Cloud, .NET, Angular, React, Node.js, Microservices, DevOps, and Cross-Platform Mobile App Development. His skill set extends into emerging fields like Data Science, Python, Azure AI/ML, and Generative AI, making him a well-rounded expert who bridges traditional development frameworks with cutting-edge advancements. Recognized as a Microsoft Most Valuable Professional (MVP) for an impressive 9 consecutive years (2016–2024), he has consistently demonstrated excellence in delivering impactful solutions and inspiring learners.

Shailendra’s unique, hands-on training programs and bestselling books have empowered thousands of professionals to excel in their careers and crack tough interviews. A visionary leader, he continues to revolutionize technology education with his innovative approach.
Accept cookies & close this