Method Overloading and Method Overriding
Method Overloading and Method Overriding
Chapter 6 introduced overloading and overriding as the two faces of polymorphism. This chapter goes deeper: the exact rules Java enforces for each, where they are used in practice, and the small but important differences beginners often mix up between them.
What is Method Overloading?
Method overloading happens when a class contains two or more methods that share the same name but accept a different set of parameters. It lets a single, memorable method name handle several related variations of the same basic operation.
class Printer {
void print(String text) {
System.out.println(text);
}
void print(String text, int copies) {
for (int i = 0; i < copies; i++) {
System.out.println(text);
}
}
}
Callers can use print("Hello") for a single copy, or print("Hello", 3) for three, without needing to remember two completely different method names for what is conceptually the same action.
Rules of Method Overloading
• The method name must stay exactly the same across all overloaded versions.
• The parameter list must differ, either in the number of parameters, their data types, or their order.
• The return type alone is not enough to distinguish two overloads; two methods with identical parameter lists but different return types will not compile.
• Overloaded methods can have different access modifiers and can optionally throw different exceptions, neither affects whether overloading is valid.
• Overloading can happen within the same class, or between a superclass and subclass (a subclass can add a new overload alongside an inherited one).
class Demo {
void show(int x) { }
// void show(int y) { } // INVALID — identical parameter list, won't compile
void show(int x, int y) { } // VALID — different number of parameters
void show(double x) { } // VALID — different parameter type
}
What is Method Overriding?
Method overriding happens when a subclass provides its own implementation of a method that is already defined in its superclass, using the exact same method name and exact same parameter list. Unlike overloading, overriding always involves two classes connected by inheritance.
class Employee {
double calculateBonus() {
return 1000;
}
}
class Manager extends Employee {
@Override
double calculateBonus() {
return 5000;
}
}
A Manager object calling calculateBonus() will always return 5000, never falling back to the Employee version, because the subclass's implementation takes priority at runtime.
Rules of Method Overriding
• The method name and the parameter list must match the superclass version exactly.
• The return type must be the same, or a covariant type, a subtype of the original return type.
• The access modifier in the subclass cannot be more restrictive than in the superclass; you can widen visibility (protected to public) but never narrow it (public to private).
• A method marked final, static, or private in the superclass cannot be overridden; static methods can only be hidden, not truly overridden, and final methods are locked against any redefinition.
• The overriding method cannot throw a broader checked exception than the one declared in the superclass version.
class Vehicle {
protected String start() {
return "Vehicle starting";
}
}
class Car extends Vehicle {
@Override
public String start() { // widening protected -> public is fine
return "Car engine starting";
}
}
Overloading vs Overriding
Aspect | Method Overloading | Method Overriding |
Classes involved | Usually one class (can also span superclass/subclass) | Always two classes, linked by inheritance |
Parameter list | Must differ | Must be identical |
Return type | Can differ freely | Must match, or be a covariant subtype |
Resolved by | Compiler, at compile time | JVM, at runtime |
Polymorphism type | Compile-time (static) | Runtime (dynamic) |
Purpose | Offer multiple ways to call a similarly-named operation | Let a subclass customise inherited behaviour |
Use Cases and Examples
Overloading shows up constantly in everyday Java code, even code you have not written yourself. The println() method you have used throughout this tutorial is itself overloaded many times over, to accept a String, an int, a double, a boolean, and more, all under one familiar name.
System.out.println("Hello"); // calls println(String)
System.out.println(42); // calls println(int)
System.out.println(3.14); // calls println(double)
System.out.println(true); // calls println(boolean)
Overriding shows up wherever a framework or library expects you to customise default behaviour. Almost every Java class implicitly inherits toString() from Object, and overriding it is one of the most common pieces of overriding you will write in real projects, so that printing an object shows something meaningful instead of a generic memory reference.
class Book {
String title;
Book(String t) {
title = t;
}
@Override
public String toString() {
return "Book: " + title;
}
}
Book b = new Book("Java Basics");
System.out.println(b); // Book: Java Basics — instead of a memory address
Quick Tip
If you are ever unsure whether two methods overload or override each other, ask one question: are they in the same class with different parameters (overloading), or in a parent-child pair with the identical signature (overriding)? That single distinction resolves almost every confusion beginners run into here.










