Both reuse a method name, but they're fundamentally different. = same name, , in the same class, resolved at . = a subclass a parent method with the , resolved at .
Both reuse a method name, but they're fundamentally different. = same name, , in the same class, resolved at . = a subclass a parent method with the , resolved at .
| Overloading | Overriding | |
|---|---|---|
| Signature | Must differ (params) | Must be identical |
| Relationship | Same class | Parent ↔ subclass |
| Resolved | Compile time (static) | Runtime (dynamic) |
| Purpose | Convenience / variants | Polymorphism |
class Printer {
void print(String s) { System.out.println(s); }
void print(int n) { System.out.println(n); } // same name, diff param
void print(String s, int times) { /* ... */ }
}
The compiler picks which print based on argument types — no inheritance involved.
class Animal { String speak() { return "..."; } }
class Dog extends Animal {
@Override
String speak() { return "Woof"; } // replaces Animal.speak()
}
Animal a = new Dog();
a.speak(); // "Woof" — runtime picks Dog's version (dynamic dispatch)
A frequent mistake is accidentally overloading when you meant to override (e.g. a typo in the signature). Always use @Override (Java) or override (C#) so the compiler catches it.
Overriding is the engine of polymorphism — the runtime mechanism that makes "one interface, many implementations" work.
Knowing the difference prevents a classic bug: thinking you replaced behavior when you actually created a second, never-called method.