Java Method Overriding


In Java, method overriding is a feature that allows a subclass to provide a specific implementation for a method that is already defined in its superclass. This is a key concept in object-oriented programming (OOP) and is essential for achieving polymorphism in Java. When a method in a subclass has the same signature as a method in its superclass, the subclass method is said to override the superclass method.

This guide will help you understand what method overriding is, its syntax, how it works, and provide practical examples to illustrate the concept.

Table of Contents

  1. What is Method Overriding in Java?
  2. Syntax of Method Overriding
  3. Key Points About Method Overriding
  4. Example of Method Overriding
  5. Rules of Method Overriding
  6. Using super Keyword with Method Overriding
  7. Method Overriding and Polymorphism
  8. Benefits of Method Overriding
  9. Common Pitfalls of Method Overriding

What is Method Overriding in Java?

Method overriding in Java allows a subclass to redefine the behavior of a method that is already defined in its superclass. The method in the subclass must have the same name, return type, and parameters as the method in the superclass to override it.

Overriding is used when the behavior of an inherited method needs to be customized for the subclass. This provides more specific behavior than the superclass method while maintaining the same method signature.


Syntax of Method Overriding

The syntax for overriding a method in Java is quite simple. Here's the basic structure:

class Superclass {
    // Method in the superclass
    void display() {
        System.out.println("Display in Superclass");
    }
}

class Subclass extends Superclass {
    // Overriding the method in the subclass
    @Override
    void display() {
        System.out.println("Display in Subclass");
    }
}

In the above example:

  • display() is defined in both the superclass and the subclass.
  • The subclass provides its own implementation of the display() method, which overrides the superclass method.

Key Points About Method Overriding

  • Same Method Signature: The method in the subclass must have the same name, return type, and parameters as the method in the superclass.
  • @Override Annotation: While optional, it is good practice to use the @Override annotation in the subclass to indicate that the method is intended to override a method in the superclass.
  • Access Modifier: The access modifier in the subclass method cannot be more restrictive than the superclass method. For example, if the superclass method is public, the subclass method must be public or more permissive.
  • Return Type: The return type of the overridden method in the subclass must be the same as the return type of the method in the superclass (or a subtype).
  • Method Overloading vs. Overriding: Overloading occurs when two methods have the same name but different parameters. Overriding occurs when the method signature is identical in both the superclass and subclass.

Example of Method Overriding

Let’s look at a practical example to understand method overriding.

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }
}

class Main {
    public static void main(String[] args) {
        Animal animal = new Animal();
        animal.sound();  // Output: Animal makes a sound

        Dog dog = new Dog();
        dog.sound();     // Output: Dog barks

        // Polymorphism example
        Animal animalDog = new Dog();
        animalDog.sound();  // Output: Dog barks
    }
}

Output:

Animal makes a sound
Dog barks
Dog barks

In this example:

  • The sound() method is overridden in the Dog class to provide a specific implementation.
  • The third call demonstrates polymorphism, where a reference of type Animal is used to call the sound() method on an object of type Dog.

Rules of Method Overriding

When overriding a method, the following rules must be followed:

  1. Same Signature: The method name, return type, and parameters must be the same as in the superclass.
  2. Access Modifier: The access level of the overridden method must be the same or more permissive than that of the superclass method.
    • For example, if the superclass method is protected, the overridden method can be protected or public, but not private.
  3. Return Type: The return type must be the same as the superclass method or a subclass of the return type (covariant return type).
  4. No Static Methods: Static methods cannot be overridden, as they are resolved at compile-time and are not dispatched based on object type.
  5. Final, Static, and Private Methods: Final, static, and private methods cannot be overridden.
    • Final methods cannot be overridden because they are considered "locked" in the superclass.
    • Static methods belong to the class, not the instance, so they are hidden, not overridden.
    • Private methods are not inherited by the subclass, so they cannot be overridden.

Using super Keyword with Method Overriding

The super keyword is used to call the superclass method from within the subclass. It can be useful when you want to use the overridden method in addition to providing specific behavior in the subclass.

Example:

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        super.sound();  // Calls the superclass method
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.sound();
    }
}

Output:

Animal makes a sound
Dog barks

Here, the super.sound() statement calls the sound() method from the Animal class before executing the sound() method in the Dog class.


Method Overriding and Polymorphism

Polymorphism is one of the main benefits of method overriding. When an object of a subclass is referred to by a superclass reference, the method in the subclass is invoked at runtime. This is known as runtime polymorphism.

Example:

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

class Dog extends Animal {
    @Override
    void sound() {
        System.out.println("Dog barks");
    }
}

class Main {
    public static void main(String[] args) {
        Animal animal = new Dog(); // Animal reference but Dog object
        animal.sound();  // Output: Dog barks
    }
}

Output:

Dog barks

In this case, even though the reference is of type Animal, the method sound() from the Dog class is called due to method overriding.


Benefits of Method Overriding

  1. Dynamic Method Dispatch: Method overriding allows Java to determine at runtime which method to call, enabling dynamic behavior.
  2. Flexibility: It provides flexibility in defining different behaviors in subclasses, ensuring that the subclass can provide its own implementation of methods defined in the superclass.
  3. Code Reusability: The superclass code is reused, and only the specific behaviors in the subclass are modified, reducing redundancy.

Common Pitfalls of Method Overriding

  1. Incorrect Method Signature: If the method signature in the subclass does not match that of the superclass, it is not considered overriding, but method overloading.
  2. Access Modifier Issues: The access modifier of the overridden method should not be more restrictive than the superclass method. For instance, you cannot override a public method with a private method.
  3. Not Using @Override: While optional, forgetting to use the @Override annotation can lead to mistakes, such as mismatched method signatures or typos.