Method Overriding in Java (with Examples)

Method overriding in Java means redefining a method in a subclass to replace or customize the functionality of a method inherited from the superclass. When the method of superclass is overridden in the subclass to provide more specific implementation, it is called method overriding.

In other words, when the superclass method is available to subclass by default through inheritance and subclass does not satisfy with superclass implementation, the subclass is allowed to redefine that method according to its own requirements. This feature is called method overriding in Java.

By default, a subclass inherits all non-private, non-static methods from the superclass via inheritance. If you are not satisfied with the implementation (or functionality or behavior) of an inherited method, you do not need to modify that method in the superclass. This is because changing the code inside method is not a good idea. Instead, you should extend that class and override it by specifying a new implementation in the subclass.

To override a method in a subclass, the method must be defined in the subclass using the same signature and same or covariant return type as the method in its superclass. Look at the below figure.

An example of performing method overriding in Java.

What is Overridden Method and Overriding Method in Java?


The superclass method being overridden is called overridden method in Java. The subclass method which is overriding the superclass method is called overriding method in Java. In other words, the method in the subclass that provides the new implementation is called the overriding method. Look at the above figure.

Note: Method overriding only occurs when the method signatures (i.e. name and parameter list) of the superclass and subclass methods are identical. If the signatures are different, even slightly (like different number or type of parameters), then it’s simply method overloading, not overriding.

When to Use Method Overriding in Java?


Method overriding in Java programming is useful when a subclass needs to provide a specific implementation of a method that is already defined in its superclass. It enables runtime polymorphism and allows behavior to be customized in subclasses without modifying the existing superclass code.

Let’s take a simple real-life example to understand the need for method overriding in Java.

Real-life Scenario:

Assume that a young couple wants to marry. They plan their engagement and marriage dates. They initially decide:

  • Engagement: 23rd December
  • Marriage: 25th December

We will create a class Marry to represent this plan:

public class Marry 
{ 
   void engagementDate() 
   { 
      System.out.println("Engagement will be done on 23 December."); 
   } 
// Overridden method. 
   void marryDate() 
   { 
      System.out.println("Marry will be on 25 December"); 
   } 
}

But later, due to Christmas day on 25th December, the young couple decides to change the date of marrying. Now, what should you do?

Bad Practice:

A common but bad approach is that you will open the existing Marry class and edit the marryDate() method to change the marriage date. If you also think to do, this is the worst programming practice because this violates the open/closed principle of object-oriented programming design.

This principle states that classes should be open for extension, but closed for modification. Modifying existing, tested, or reused classes is considered bad programming practice because it can:

  • Introduce bugs into working code.
  • Break dependencies for other classes using it.
  • Violate design principles.

Good Practice – Using Method Overriding

If you want to add new functionality to the existing class or if you want to modify the existing functionality of the class, you should not disturb the existing class. You should always create a subclass of the existing class and override the marryDate() method to add new functionality in subclass like this:

public class Change extends Marry 
{ 
 // Overriding method.
   @Override 
   void marryDate() 
   { 
     System.out.println("Marry will be on 27 December."); 
   } 
 }

Now, test it in the main() method:

public class MyClass { 
public static void main(String[] args) 
{ 
     Change obj = new Change(); 
     obj.engagementDate(); // Inherited from superclass.
     obj.marryDate(); // Overridden method in subclass.
 } 
}
Output: 
       Engagement will be done on 23 December. 
       Marry will be on 27 December.

In this example, the Change subclass is implementing marryDate() method with the same signature as in the superclass marryDate() method. The Change class extends the Marry class and overrides the marryDate() method. The engagementDate() method remains unchanged and is reused from the superclass. Thus, the new behavior or functionality is added without touching the existing class.

From the above example, it’s clear that

  • Overriding allows you to change specific behavior without altering existing code.
  • It promotes code reuse, modularity, and maintainability.
  • It adheres to good object-oriented programming practices.

Features of Method Overriding


Method overriding is one of the most powerful features of object-oriented programming in Java. It allows a subclass to provide a specific implementation of a method that is already defined in its superclass. It enables us to customize the behavior of a method in the subclass while maintaining the same method signature as the method in the superclass.

There are the following key features of the method overriding in Java. They are as follows:

  • Method overriding technique supports the runtime polymorphism. This allows method calls to be resolved at runtime, enabling dynamic method dispatch.
  • It allows a subclass to provide its own implementation of the method which is already provided by the superclass.
  • Only the instance method (i.e. non-static) can be overridden in Java.
  • An instance variable can never be overridden in Java.
  • The overriding method can not be more restrictive access modifiers than the overridden method of the superclass. For example, a public method in the superclass cannot be overridden as protected or private.
  • Overriding concept is not applicable for private, final, static, and main method in Java.
  • From Java 5 onwards, the return type of the overriding method can be a subclass of the return type declared in the superclass. This is known as a covariant return type.
  • The overriding method cannot throw any checked exception.

Rules for Method Overriding in Java


When you are overriding superclass method in a subclass, you need to follow certain rules. They are as follows.

1. The name of subclass method must have exactly the same name as the superclass method name.

2. The parameter list (types or order) of the subclass method must be the same as the superclass method parameters. In overriding, method name and argument types must be matched. If the method name is the same but the parameters differ, it’s method overloading, not overriding.

3. Must be Is-A relationship (Inheritance). Overriding is only possible through inheritance. The subclass must inherit the method from the superclass.

4. Subclass method’s return type must be the same as the superclass method return type. But this rule is applicable until the Java 1.4 version only. From the Java 1.5 version onwards, covariant return types are also allowed.

5. Subclass method’s access modifier must be the same or more permissive than the superclass method access modifier. In other words, the overriding method cannot be more restrictive than the overridden method. It can be the same or less restrictive. Look at the below figure to understand better.

Applicable access modifiers to overriding method in Java.

While the overriding, you can increase the visibility of the overriding method but cannot reduce it. For example, if the superclass method is protected, you can override as a public method in the subclass.

Similarly, a method with default (package-private) access in the superclass can be overridden in the subclass using default, protected, and public. But you cannot override it as private.


You cannot override a public method with a protected, default, or private method. You cannot override a method if we do not inherit it. For example, a private method cannot be overridden because it cannot be inherited in the subclass.

6. The overriding method cannot throw new or broader checked exceptions than the method it overrides. However, it can throw fewer, narrower or unchecked (runtime) exceptions.

Why do We Need to Create Subclass in Java?


In Java, creating a subclass from an existing superclass is a fundamental concept of object-oriented programming. A subclass allows you to build on an existing class and extend or modify its functionality without changing the original class. There are three main reasons for creating a subclass in Java:

1. To add new features or properties without modifying existing class. For example, a student has properties like age and location. But in the future, if we get a new requirement to add one more property “address” for that student, we should make a subclass of that class and add a new property address in the subclass.

class Student {
    int age;
    String location;
}
// Subclass with adding additional feature.
class AddNewFeature extends Student {
    String address;  // New property added.
}

2. To override or change the existing functionality defined in the superclass method. For example, if a method defined in the superclass doesn’t meet your specific requirement, you can create a subclass and override that method to provide a new implementation.

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

3. To inherit the existing functionality of the superclass method. A subclass automatically inherits fields and methods from its superclass. This allows you to reuse code efficiently without duplicating it in multiple classes.

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

class Car extends Vehicle {
    // Inherits start() from Vehicle.
}

Thus, it promotes code reusability and supports the DRY (Don’t Repeat Yourself) principle in programming.

What is @Override Annotation in Java?


The @Override annotation was introduced in Java 5. This annotation instructs the compiler that the method is intended to override a method from its superclass or implement a method from an interface. If the method does not match any method in the superclass or interface, the compiler will throw an error.

The @Override annotation helps to catch errors early during compile-time, especially those caused by:

  • Mistyped method names.
  • Incorrect method signatures.
  • Attempting to override private, static, or final methods.

a) Without Annotation:

Without @Override annotation, the compiler will apply only basic overriding rules, such as name, parameters, and Is-A relationship. For example:

class Superclass {
  private void msg()
  {
     System.out.println("Hello");
  }
}
class Subclass extends Superclass {
// No overriding and no compile-time error.
  private void msg()
  {
     System.out.println("Hi")
  }
}

Compile-time: OK (no error), Runtime: OK. Both methods exist independently because private methods are not inherited, so no real overriding is happening.

b) With Annotation:

With @Override annotation, the compiler strictly enforces all rules and gives the compile-time error if overriding is invalid. For example:

class Superclass {
   private void msg()
   {
     System.out.println("Hello");
   }
}
class Subclass extends Superclass
   @Override
   private void msg() // Compile-time error
   {
      System.out.println("Hi");
   }
}

Compile-time: Error- private method cannot be overridden. Runtime: OK

When to Use @Override Annotation in Java?


Always use @Override annotation whenever you are overriding a method from a superclass or implementing an interface. This improves code readability and understanding.

For example, suppose a developer leaves your project and another new one joins. By looking at @Override, the new developer will easily understand this method is intended to override a superclass method. Thus, he can modify it easily in the future. At least he/she will understand that there is some relationship between the two methods.

How Java Determines Which Method to Execute at Runtime?


In method overriding, the Java compiler does not decide which method is to be executed. This is because the decision depends on the runtime type of the object, not the reference variable’s type. At compile-time, the method call is checked against the reference type.

In method overriding, Java Virtual Machine (JVM) decides the method call depending on the runtime object of the class. When the object of subclass is created, JVM binds the method call to the suitable method.

Method selection is always resolved by JVM based on the runtime object. During runtime, the actual object of the class is used to call the method. This mechanism is called runtime polymorphism or dynamic method dispatch in Java.

Basic Examples of Method Overriding in Java


Let’s start with a simple example program to demonstrate how overriding works.

Example 1:

package overridingProgram;
public class A 
{ 
   void m1()
   { 
      System.out.println("A-m1"); 
   } 
// Overridden method. 
   void m2()
   { 
      System.out.println("A-m2"); 
   } 
 } 
public class B extends A 
{ 
 // Overriding method. 
    void m2()
    { 
       System.out.println("B-m2"); 
    } 
 // Newly defined method in class B. 
    void m3()
    { 
       System.out.println("B-m3"); 
    } 
 } 
 public class MyTest { 
 public static void main(String[] args) 
 { 
    A a = new A(); 
    a.m1(); 
    a.m2(); 
  
    B b = new B(); 
    b.m1(); 
    b.m2(); 
    b.m3(); 
  
    A a1 = new B(); 
    a1.m1(); 
    a1.m2(); 
  } 
 }
Output: 
       A-m1 
       A-m2 
       A-m1 
       B-m2 
       B-m3 
       A-m1 
       B-m2

Explanation:

1. The statement a.m1(); will call m1() method of class A because the reference variable ‘a’ is pointing to the object of class A. Similarly, a.m2() will also call m2() method of class A.

2. The statement b.m1(); will call m1() method of class B because m1() of class A is available by default to class B due to inheritance and the reference variable ‘b’ is pointing to the objects of class B. Similarly, the line b.m2() will call m2() method of class B because ‘b’ is pointing to the objects of the class. b.m3(); will call the method of class B.

3. The line A a = new B(); tells that the reference variable ‘a1’ of class A is pointing to the objects of class B. That is, the parent reference variable can hold child class object.

4. Line a1.m1(); will call the m1() method of class B because it is available by default.

5. a1.m2(); will call m2() method of class B because the reference variable a1 is pointing to objects of class B.

Role of Java Compiler and JVM in Method Overriding


Role of Java compiler in overriding:

During the compile-time in the above program (A a1), a1 is a reference variable of parent class A. i.e. a1 is of parent type. So, Java compiler will be gone to check that m2() method is available or not. If it is available in the parent class, no problem. The code will be happily compiled.

Role of JVM in overriding:

At runtime, JVM will check that the reference variable is pointing to the which class object? parent class object or child class object.

If it is pointing to the parent class object and m2() method is available in the parent class, it will execute the m2() method of the parent class. But if it is pointing to the child class object, JVM will immediately check that in the child class, the m2 method is overriding or not.

If it is not overriding in the child class, JVM will call the default parent m2 method available in the child class. Thus, JVM will execute the parent method only.

If the m2 is overriding in the child class, at the runtime, JVM will execute the child class method based on the runtime object (new B()). In the overriding method, the method resolution is always based on the runtime object by JVM.

Example 2: Increasing the Visibility of an Overriding Method in Java

package overridingProgram; 
public class College 
{ 
   public void collegeName()
   { 
      System.out.println("Name of college is PIET."); 
   } 
// Overridden method. 
   void estYear()
   { 
      System.out.println("It was established in 1999."); 
   } 
} 
public class MyCollege extends College 
{ 
// Here, we are increasing visibility the overriding method. 
   protected void estYear()
   { 
      System.out.println("It was established in 2001."); 
   } 
} 
public class Test { 
public static void main(String[] args) 
{ 
    MyCollege mc = new MyCollege(); 
    mc.collegeName(); 
    mc.estYear(); 
  
    College c = new MyCollege(); 
    c.estYear(); 
  } 
}
Output: 
       Name of college is PIET. 
       It was established in 2001. 
       It was established in 2001.

Example 3: Reducing the Visibility of Overriding Method in Java

package overridingProgram; 
public class X 
{ 
   public void m1()
   { 
      System.out.println("m1-X"); 
   } 
} 
public class Y extends X 
{ 
// Here, we are reducing the visibility of overriding method. So, it will generate compile time error. 
// We cannot reduce the visibility of inherited method from X.
   void m1()  
   { 
      System.out.println("m1-Y"); 
   } 
 } 
public class XY { 
public static void main(String[] args) 
{ 
     Y y = new Y(); 
     y.m1(); 
  } 
}
Output: 
       Error: Unresolved compilation problem: Cannot reduce the visibility of the inherited method from X

Why Method Overriding is Called Runtime Polymorphism?


In Java, method overriding is known as runtime polymorphism, also called dynamic polymorphism or late binding, because the decision of which method to execute is made at runtime based on the actual object type. Let’s understand this with a simple example code.

Example 4:

class A {
   void m2() {
      System.out.println("A - m2");
   }
}
class B extends A {
   @Override
   void m2() {
      System.out.println("B - m2");
   }
}
public class Test {
public static void main(String[] args) {
    A a1 = new B();  // Here, reference type is A, and object type is B.
    a1.m2(); // Method call
  }
}
Output:
     B - m2

In this example, the reference variable a1 is of type A, which is the superclass. However, the actual object created is of type B, which is the subclass. At compile-time, the compiler only checks whether m2() method exists in class A. Since it does, the code compiles successfully.

At runtime, the JVM sees that the actual object is of type B (subclass). Since the m2() method is overridden in class B, it executes the method defined in the class B. The method call a1.m2() is resolved at runtime based on the actual object type (new B()), not the reference type (A). This behavior is known as runtime polymorphism, dynamic method dispatch, or late binding.

Why cannot Private Method be Overridden?


In Java, you cannot override private methods because they are not visible to subclasses. When you declare a method as private, it is accessible only within the class in which it is defined.

So, if you try to declare a method with the same signature in the subclass, it is not considered as a overriding method. This will be treated as a new method that is completely unrelated to the method present in the superclass. Let’s understand this with an example.

Example 5:

package overridingProgram; 
class Parent {
   private void display() {
      System.out.println("Display from Parent");
   }
   public void callDisplay() {
      display(); // Calls Parent's private method
   }
}
class Child extends Parent {
 // This is not an overridden method. It is a new method.
    public void display() {
        System.out.println("Display from Child");
    }
}
public class Test {
public static void main(String[] args) {
     Child obj = new Child();
     obj.display(); // Calls Child's display() method.
     obj.callDisplay(); // Calls Parent's display() method internally.
   }
}
Output:
       Display from Child  
       Display from Parent

In this example, we have declared the display() method in the Parent class as private, so the Child class does not inherit it. Even though we define a method with the same name and signature in the Child class, still it is a completely new method, not an overridden version of the parent method. When we have called the callDisplay(), it still invokes the Parent class’s private method because the subclass has no access to it.

Can We Override Static Method in Java?


No, we cannot override a static method. We cannot also override a static method with an instance method because the static method is bound with class whereas an instance method is bound with an object.

For more detail, go to this tutorial: Can we override static method in Java in 3 cases?

Example 6:

package overridingProgram; 
public class X 
{ 
  static void m1()
  { 
    System.out.println("m1-X"); 
  } 
} 
public class Y extends X
{ 
 @Override 
 static void m1() // Compile time error because the method m1() of type Y must override or implement a supertype method. 
 { 
   System.out.println("m1-Y"); 
 } 
} 
public class XY { 
public static void main(String[] args) 
{ 
    Y y = new Y(); 
    y.m1(); 
 } 
}

Can We Stop Method Overriding in Java?


Yes, we can stop method overriding by declaring method as final. Let’s take a simple example program where we will declare the overriding method as final in the subclass and will try to override the method in subclass.

Example 7: 

package overridingProgram; 
public class X 
{ 
// Overridden method. 
   void m1()
   { 
     System.out.println("m1-X"); 
   } 
} 
public class Y extends X
{ 
  @Override 
  final protected void m1() // By declaring method as final, we can stop overriding. 
  { 
     System.out.println("m1-Y"); 
  } 
} 
public class XY extends Y
{ 
   @Override
   public void m1() // Cannot override the final method from Y. 
   { 
     System.out.println("m1-XY"); 
   } 
public static void main(String[] args) 
{ 
   Y y = new Y(); 
   y.m1(); 
 } 
}

Can Constructors Be Overridden?


No. Constructors cannot be overridden because they are not inherited in the subclass. However, they can be overloaded.

Advantages of Using Method Overriding in Java


There are the following advantages of using method overriding in Java. They are as:

  • Method overriding is used to achieve runtime polymorphism in Java.
  • It is used to change the existing functionality of the superclass method.
  • Method overriding allows us to extend the functionality of a superclass without altering its original implementation. We can add a new feature or property in subclass.
  • By defining a common method in the superclass and then allowing subclasses to override it, we can prevent the code duplication across different subclasses.
  • If you want the same method signature with different behaviors in the superclass as well as subclass, then you should use method overriding.
DEEPAK GUPTA

DEEPAK GUPTA

Deepak Gupta is the Founder of Scientech Easy, a Full Stack Developer, and a passionate coding educator with 8+ years of professional experience in Java, Python, web development, and core computer science subjects. With strong expertise in full-stack development, he provides hands-on training in programming languages and in-demand technologies at the Scientech Easy Institute, Dhanbad.

He regularly publishes in-depth tutorials, practical coding examples, and high-quality learning resources for both beginners and working professionals. Every article is carefully researched, technically reviewed, and regularly updated to ensure accuracy, clarity, and real-world relevance, helping learners build job-ready skills with confidence.