Can we change the access modifier of an overridden method in Java?

You can change the access modifier of an overridden method, but there are restrictions: you can only make the overridden method's access less restrictive, or keep it the same. You cannot make it more restrictive.

Here's a breakdown:

  • Valid Changes:

    • private -> default -> protected -> public (increasing accessibility)
    • You can also keep the access modifier the same.
  • Invalid Changes:

    • public -> protected -> default -> private (decreasing accessibility)

Why the Restriction?

The reason for this restriction is to maintain the principle of polymorphism and ensure that subclasses can be used interchangeably with their superclasses without causing unexpected access issues.

Let's illustrate with an example :

class Animal {
    public void makeSound() {
        System.out.println("Generic animal sound");
    }
}

class Dog extends Animal {
    // Valid: Widening access (public -> public) or keeping it the same
    @Override
    public void makeSound() {
        System.out.println("Woof!");
    }

    // Invalid: Narrowing access (public -> protected or default or private)
    // @Override
    // protected void makeSound() {  // Compile-time error!
    //     System.out.println("Woof!");
    // }

    // @Override
    // void makeSound() {  // Compile-time error!
    //     System.out.println("Woof!");
    // }

    // @Override
    // private void makeSound() {  // Compile-time error!
    //     System.out.println("Woof!");
    // }
}

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Animal();
        Animal myDog = new Dog(); // Polymorphism: Dog is an Animal

        myAnimal.makeSound(); // Output: Generic animal sound
        myDog.makeSound();   // Output: Woof! (Correctly calls Dog's makeSound)
    }
}

If you were allowed to make the makeSound method in Dog protected, default, or private, the line myDog.makeSound() would result in a compile-time error or a runtime exception because the makeSound method wouldn't be accessible through the Animal reference (myDog). This would break the principle of polymorphism, where you expect a Dog object to behave like an Animal object.

In essence, the access modifier of an overridden method must be at least as accessible as the access modifier of the method it overrides. This rule ensures that subclasses can be used polymorphically without violating access restrictions.