What is method overloading vs method overriding?
Quick Answer
Overloading is defining multiple methods with the same name but different parameter lists in the same class; it's resolved at compile time based on argument types (static/compile-time polymorphism). Overriding is a subclass providing a new implementation of a method inherited from its superclass with the same signature; it's resolved at runtime based on the actual object type (dynamic/runtime polymorphism).
Detailed Answer
Overloading — same method name, different parameter list, within the same class (or class hierarchy) — chosen by the compiler based on the static types of the arguments:
void print(int x) {}
void print(String s) {}
void print(int x, int y) {}
Overriding — a subclass redefines a method it inherited, with the same signature — chosen at runtime based on the object's actual (dynamic) type, via virtual dispatch:
class Animal { void sound() { System.out.println("..."); } }
class Dog extends Animal { @Override void sound() { System.out.println("Woof"); } }
Animal a = new Dog();
a.sound(); // "Woof" — decided at runtime by a's actual type
Key rules for a valid override: same name and parameter types, covariant (same or narrower) return type, no narrower access modifier, and it can't throw new/broader checked exceptions than the overridden method. The @Override annotation isn't required but catches signature mistakes at compile time.
Overloading is static polymorphism (resolved at compile time); overriding is dynamic polymorphism (resolved at runtime) — this distinction is a very common interview follow-up.