Understanding Polymorphism

1. Understanding Compile-Time Polymorphism

MechanismResolution
Method overloadingCompiler chooses based on static argument types
Operator +String concat or numeric add
GenericsType-checked at compile time

2. Understanding Runtime Polymorphism

Example: Dynamic dispatch

Animal a = new Dog("Rex");
a.speak();    // "Woof" — Dog.speak() chosen at runtime
MechanismDetail
Method overrideJVM dispatches based on runtime object type
Virtual table (vtable)Internal lookup mechanism

3. Using Upcasting

AspectDetail
DirectionSubclass → Superclass
ImplicitYes
ExampleAnimal a = new Dog();

4. Using Downcasting

AspectDetail
DirectionSuperclass → Subclass
ExplicitRequired: Dog d = (Dog) a;
RiskClassCastException if not actual subtype
SaferUse instanceof check first

5. Understanding Dynamic Method Dispatch

PhaseWhat's used
CompileReference type (for legality check)
RuntimeActual object type (for method resolution)

6. Working with Virtual Methods

Method typeDispatch
Instance (default)Virtual (overridable)
staticNon-virtual (class-bound)
finalNon-virtual (locked)
privateNon-virtual (not inherited)

7. Understanding Type Erasure in Generics

AspectDetail
Compile timeGeneric type parameters checked
RuntimeErased to Object (or upper bound)
ConsequenceCannot do x instanceof List<String>

8. Using Polymorphic Collections

Example: Polymorphic list

List<Animal> zoo = List.of(new Dog("Rex"), new Cat("Mia"));
zoo.forEach(Animal::speak);    // dispatches to subclass
PatternBenefit
Heterogeneous collectionSingle interface to many implementations
ExtensibilityAdd new subtypes without changing client code

9. Understanding Late Binding

TermMeaning
Late (dynamic) bindingMethod bound at runtime
Early (static) bindingMethod bound at compile time
Java defaultLate for instance methods, early for static/final/private