🚀 Java Polymorphism - Complete Guide

📘 Table of Contents

🧠 1. What is Polymorphism?

Polymorphism means "many forms."

In Java, it allows one object to take many forms — specifically, the same method name can behave differently depending on context.

🎯 Real-Life Analogy:

🛠 A remote control can operate a TV, a fan, or an AC — same remote (method), but different actions depending on device (object).

❓ 2. Why Use Polymorphism?

  • Code Reusability
  • Flexibility to use parent reference for child objects
  • Helps in method overriding and interface implementation
  • Reduces coupling (object can be treated generally or specifically)

🔀 3. Types of Polymorphism in Java

Type Also Called Done By Binding
Compile-time Polymorphism Static Polymorphism Method Overloading Early Binding
Run-time Polymorphism Dynamic Polymorphism Method Overriding Late Binding

⏰ 4. Early Binding vs Late Binding

Type When It Happens Example Related To
Early Binding Compile Time Method Overloading Static
Late Binding Runtime Method Overriding Dynamic

🔧 5. Method Overloading vs Method Overriding

✅ Example of Method Overloading (Compile-Time):

class Calculator {
    int add(int a, int b) {
        return a + b;
    }

    double add(double a, double b) {
        return a + b;
    }
}

public class Main {
    public static void main(String[] args) {
        Calculator c = new Calculator();
        System.out.println(c.add(2, 3));        // calls int version
        System.out.println(c.add(2.5, 3.5));    // calls double version
    }
}

✔️ Same method name (add), different parameters = overloading

✅ Example of Method Overriding (Runtime):

class Animal {
    void sound() {
        System.out.println("Animal makes sound");
    }
}

class Dog extends Animal {
    void sound() {
        System.out.println("Dog barks");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal a = new Dog(); // upcasting
        a.sound(); // Dog barks (overridden version) → runtime polymorphism
    }
}

✔️ sound() method is called based on object type, not reference type.

🧭 6. Method Dispatch in Java

🔹 Dynamic Method Dispatch:

When a parent class reference is used to refer to a child class object, and overridden method is resolved at runtime, it's called dynamic method dispatch.

✅ Example:

class Shape {
    void draw() {
        System.out.println("Drawing Shape");
    }
}

class Circle extends Shape {
    void draw() {
        System.out.println("Drawing Circle");
    }
}

public class Main {
    public static void main(String[] args) {
        Shape s = new Circle(); // upcasting
        s.draw(); // Output: Drawing Circle
    }
}

📌 The method call is resolved at runtime, depending on the actual object.

🔼 7. Upcasting & 🔽 Downcasting

🔼 Upcasting (Safe, Common):

Assigning a child object to a parent reference.

Animal a = new Dog(); // Upcasting
a.sound(); // Allowed (calls overridden method)

✔️ Safe because the object is created as a Dog, but treated generally as an Animal.

🔽 Downcasting (Risky):

Casting a parent reference back to a child object.

Animal a = new Dog(); // Upcasting
Dog d = (Dog) a;       // Downcasting
d.sound();             // Works if 'a' is actually a Dog
⚠️ Downcasting is risky because the compiler trusts you — but if the object is not of the expected type, it throws a ClassCastException at runtime.

💥 ❌ Example that causes error:

Animal a = new Cat(); // Object is actually a Cat
Dog d = (Dog) a;       // ⚠️ Wrong downcasting
d.sound();             // ❌ Runtime Error: ClassCastException
🔥 Output:
Exception in thread "main" java.lang.ClassCastException: Cat cannot be cast to Dog

✅ Safer Way Using instanceof:

if (a instanceof Dog) {
    Dog d = (Dog) a;
    d.bark();
} else {
    System.out.println("Not a Dog. Cannot downcast safely.");
}

📚 8. Summary & Interview Questions

📋 Summary Table of Polymorphism Concepts

Concept Meaning
Polymorphism One interface, many implementations
Overloading Same method name, different params (compile-time)
Overriding Child class redefines parent method (runtime)
Early Binding Method resolved at compile time
Late Binding Method resolved at runtime
Upcasting Parent reference = new Child()
Downcasting (Child) Parent reference
Dynamic Dispatch Overridden method chosen at runtime

✅ Important Interview Questions

Question Answer
What is polymorphism? OOP concept where the same method has different behaviors.
Types of polymorphism in Java? Compile-time (overloading), Runtime (overriding).
What is method overloading? Same method name, different parameters (early binding).
What is method overriding? Child class redefines parent method (late binding).
What is dynamic method dispatch? Calling overridden method using parent reference at runtime.
What is upcasting? Parent reference pointing to child object.
What is downcasting? Converting parent reference back to child.
Why is Java polymorphism powerful? Enables flexible code, loose coupling, code reuse.