100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Java

Method Overriding in Java

Understand how Java subclasses override inherited methods, the rules governing overriding, and how runtime polymorphism resolves the actual method called.

OOP AdvancedIntermediate8 min readJul 7, 2026
Analogies

1. Introduction

Method overriding occurs when a subclass provides its own specific implementation of a method that is already defined in its superclass, using the same method signature. It is the foundation of runtime (dynamic) polymorphism in Java.

🏏

Cricket analogy: A junior batter inheriting the "batting style" from a senior mentor but developing their own signature shot with the exact same stroke name is like a subclass overriding a method, same signature, own implementation, enabling runtime polymorphism.

Overriding lets a subclass customize or extend inherited behavior while still being usable wherever the superclass type is expected.

🏏

Cricket analogy: A specialist finisher can still be selected under the general "batter" role in the team sheet while bringing their own customized late-innings hitting style, like an overridden method still usable wherever the superclass type is expected.

2. Syntax

java
class Animal {
    void makeSound() {
        System.out.println("Some generic animal sound");
    }
}

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

3. Explanation

To override a method, the subclass method must have the exact same name and parameter list (signature) as the superclass method, and a compatible return type — either identical or a covariant return type (a subtype of the original return type).

🏏

Cricket analogy: To officially replace a bowler in the same over, the substitute must bowl the same type of delivery under the same over rules and deliver an outcome the umpire accepts as equivalent, like overriding requiring the same signature and a compatible return type.

Unlike overloading, overriding is resolved at runtime based on the actual object type (dynamic binding / late binding), not the reference variable's declared type. This is why Animal a = new Dog(); a.makeSound(); prints "Bark" — the JVM looks at the real object (Dog) at runtime.

🏏

Cricket analogy: Even if the scorecard lists a player under their general "all-rounder" designation, at the crease it's their actual specialized skill, say express pace, that determines what really happens, like Animal a = new Dog() resolving to Dog's actual behavior at runtime.

The @Override annotation is optional but strongly recommended: it tells the compiler to verify that the method actually overrides a superclass method, catching typos in the signature at compile time instead of silently creating an unrelated overloaded method.

🏏

Cricket analogy: Declaring "I'm taking over as strike bowler" formally with the captain lets everyone verify you actually match the required over slot instead of accidentally bowling an unscheduled extra over, like @Override catching a signature typo at compile time.

The overriding method's access modifier cannot be more restrictive than the overridden method's. For example, a public method in the superclass cannot be overridden as protected or private in the subclass.

🏏

Cricket analogy: A vice-captain's public authority to make bowling changes cannot be quietly narrowed to a private, personal decision when they step into the captain's role, just as an overriding method can't reduce a public superclass method's access to protected or private.

Exam tip: static methods, final methods, and private methods cannot be overridden. A static method with the same signature in a subclass is called 'method hiding', not overriding, and is resolved using the reference type, not the object type.

If you accidentally change the parameter list while trying to override a method, you create a new overload instead of an override — the @Override annotation prevents this mistake by failing to compile.

4. Example

java
class Animal {
    void makeSound() {
        System.out.println("Some generic animal sound");
    }
}

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

class Cat extends Animal {
    @Override
    void makeSound() {
        System.out.println("Meow");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a1 = new Dog();
        Animal a2 = new Cat();
        a1.makeSound();
        a2.makeSound();
    }
}

5. Output

text
Bark
Meow

6. Key Takeaways

  • Overriding means a subclass redefines a superclass method with the same signature.
  • Overriding is resolved at runtime based on the actual object type (dynamic binding).
  • Covariant return types are allowed; access modifiers cannot become more restrictive.
  • static, final, and private methods cannot be overridden.
  • @Override annotation helps the compiler catch signature mistakes.

Practice what you learned

Was this page helpful?

Topics covered

#Java#JavaProgrammingStudyNotes#Programming#MethodOverridingInJava#Method#Overriding#Syntax#Explanation#Functions#StudyNotes#SkillVeris