Method Overriding
What Is Method Overriding?
Method overriding happens when a subclass provides its own implementation of a method that its superclass already defines. To count as an override, the subclass method must have exactly the same signature as the parent's — same name, same parameter types, same order — and a compatible return type. When you call that method on a subclass object, the subclass's version runs instead of the parent's, even if you're holding a superclass-typed reference.
A basic override
public class Employee {
double calculateBonus() {
return 500.0;
}
}
public class SalesEmployee extends Employee {
@Override
double calculateBonus() {
return 1500.0; // overrides Employee's version
}
}
public class Main {
public static void main(String[] args) {
Employee e = new SalesEmployee(); // superclass reference, subclass object
System.out.println(e.calculateBonus()); // runs SalesEmployee's version
}
}1500.0
The @Override Annotation
Always mark an intended override with the @Override annotation. It doesn't change how the method behaves, but it tells the compiler to verify that the method actually overrides something from a parent class or interface.
@Override
double calculatebonus() { ... } // wrong case! compiler flags this as an error
Overriding vs. Overloading
Overriding and overloading are often confused because both involve multiple methods sharing a name, but they solve completely different problems.
Aspect | Overriding | Overloading |
Signature | Must be identical to the parent method's | Must differ (parameter count, order, or types) |
Relationship | Requires inheritance (a subclass and a superclass, or a class and an interface) | Can happen within a single class |
Resolved | At runtime, based on the object's actual type (dynamic dispatch) | At compile time, based on the arguments used in the call |
Purpose | Let a subclass customize or replace inherited behavior | Offer several convenient ways to call conceptually the same operation |
Return type | Must be the same type, or a covariant (narrower) subtype | Can be anything — return type alone doesn't distinguish overloads |
Rules for Overriding
The method name and parameter list must match the parent method exactly
The return type must be the same, or a covariant (subtype) return
An overriding method cannot reduce the visibility of the method it overrides — a public parent method cannot become protected or private in the subclass
An overriding method cannot throw new or broader checked exceptions than the parent method declares (it may throw fewer, or narrower, checked exceptions)
static, private, and final methods cannot be overridden — static methods are hidden rather than overridden, and private/final methods aren't inheritable for overriding at all
Visibility cannot be reduced
public class Parent {
public void greet() {
System.out.println("Hello from Parent");
}
}
public class Child extends Parent {
@Override
protected void greet() { // compile error: reduces visibility from public to protected
System.out.println("Hello from Child");
}
}Always annotate intended overrides with @Override so the compiler catches signature mistakes for you
Keep overriding methods' visibility the same or wider than the parent's
Don't declare new or broader checked exceptions on an overriding method
Reserve overloading for genuinely alternative ways to call the same conceptual operation, and overriding for genuinely customizing inherited behavior