Method overloading vs. method overriding serve different purposes and operate at different levels.Lets understand clearly, compare them, and provide examples to make it crystal clear.
Definitions:
Method Overloading:
- What: Defining multiple methods in the same class with the same name but different parameter lists (number, type, or order of parameters).
- When: At compile-time (static polymorphism).
- Purpose: Increases flexibility by allowing different ways to call a method based on input.
Method Overriding:
- What: Redefining a method in a subclass that is already defined in a superclass, with the same signature (name, parameters, return type).
- When: At runtime (dynamic polymorphism).
- Purpose: Customizes or extends superclass behavior in the subclass.
Key Differences:
Aspect | Method Overloading | Method Overriding |
---|---|---|
Definition | Same name, different parameters | Same name, same parameters |
Class Level | Within the same class | Between superclass and subclass |
Polymorphism | Compile-time (static) | Runtime (dynamic) |
Signature | Differs (parameters) | Identical (name, params, return type) |
Inheritance | Not required | Requires inheritance (extends) |
Keyword | None | @Override (optional, recommended) |
Return Type | Can differ | Must match (or covariant in Java 5+) |
Access Modifier | Can differ | Can’t reduce visibility |
Examples:
Method Overloading Example:
public class Calculator {
// Overloaded methods
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
public int add(int a, int b, int c) {
return a + b + c;
}
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3)); // Calls int version: 5
System.out.println(calc.add(2.5, 3.5)); // Calls double version: 6.0
System.out.println(calc.add(1, 2, 3)); // Calls three-param version: 6
}
}
- Output:
5 6.0 6
- Why: The compiler picks the method based on the argument types and number at compile-time.
Method Overriding Example
class Animal {
public void sound() {
System.out.println("Generic animal sound");
}
}
class Dog extends Animal {
@Override
public void sound() { // Overrides superclass method
System.out.println("Woof Woof");
}
}
public class OverridingExample {
public static void main(String[] args) {
Animal generic = new Animal();
Animal dog = new Dog(); // Polymorphism
generic.sound(); // Generic animal sound
dog.sound(); // Woof Woof (runtime decision)
}
}
- Output:
Generic animal sound Woof Woof
- Why: The JVM decides which sound() to call at runtime based on the object’s actual type (Dog), not the reference type (Animal).
Detailed Comparison
1. Scope
- Overloading: Same class—e.g., multiple add() methods in Calculator.
- Overriding: Across classes—e.g., sound() redefined in Dog from Animal.
2. Signature
- Overloading: Must differ in parameters (e.g., add(int, int) vs. add(double, double)).
- Overriding: Must match exactly (e.g., sound() in both Animal and Dog).
3. Polymorphism
- Overloading: Compile-time—compiler resolves based on method signature.
- Overriding: Runtime—JVM uses the object’s type (dynamic dispatch).
4. Return Type
- Overloading: Can vary (e.g., int vs. double), though not the sole differentiator.
- Overriding: Must match or be covariant (e.g., Number in superclass, Integer in subclass, Java 5+).
5. Access Modifiers
- Overloading: No restrictions—can be public, private, etc.
- Overriding: Can’t reduce visibility (e.g., public in superclass can’t become protected).
Rules and Gotchas
Overloading
- Invalid Example:java
public int add(int a, int b) { return a + b; } public String add(int x, int y) { return "Sum"; } // Error: Only return type differs
- Why: Parameters must differ—return type alone isn’t enough.
Overriding
- Rules:
- Must use @Override (optional but good practice).
- Can’t throw broader exceptions than the superclass method.
- Invalid Example:java
class Animal { void sound() throws IOException {} } class Dog extends Animal { void sound() throws Exception {} // Error: Broader exception }
Summary:
- Overloading: Same name, different flavors—compile-time flexibility in one class.
- Overriding: Same name, new behavior—runtime customization via inheritance.
For an interview, explain the difference, demo with code, and highlight polymorphism types. Want a deeper dive (e.g., covariant returns)? Let me know! What’s your next Java topic?