Lesson 11 / 25
Run-Time Polymorphism and Dynamic Dispatch
Explain dynamic dispatch, upcasting, downcasting and instanceof.
The object decides which method runs
Run-time (dynamic) polymorphism happens through overriding: a variable declared with a superclass or interface type can refer to objects of many subclasses, and calling a method runs the version of the actual object's class, chosen at run time. This is dynamic dispatch. In Java all non-static, non-final, non-private instance methods are dispatched dynamically; C++ requires the virtual keyword (and implements dispatch with a virtual table, a per-class table of function pointers). Treating a Dog as an Animal is upcasting, which is always safe and implicit. Converting back, (Dog) animal, is downcasting, which can fail at run time with ClassCastException if the object is not actually a Dog; check first with instanceof, and in modern Java use pattern matching (if (animal instanceof Dog d)) or switch patterns over sealed hierarchies. Frequent downcasting is a design smell: it usually means behaviour belongs in an overridden method instead.
One loop, many behaviours
The declared type is Shape; each object runs its own area().
List<Shape> shapes = List.of(new Circle(1), new Square(2), new Circle(0.5));
double total = 0;
for (Shape s : shapes) {
total += s.area(); // dynamic dispatch: Circle.area or Square.area
}
Shape s = new Square(3); // upcasting: implicit and safe
if (s instanceof Square sq) { // pattern matching (Java 16+)
System.out.println(sq.perimeter());
}
// sealed hierarchy + switch pattern matching (Java 21+): exhaustive by construction
sealed interface Payment permits Upi, Card, Cash {}
record Upi(String vpa) implements Payment {}
record Card(String last4) implements Payment {}
record Cash() implements Payment {}
static String label(Payment p) {
return switch (p) {
case Upi u -> "UPI " + u.vpa();
case Card c -> "Card ending " + c.last4();
case Cash c -> "Cash";
};
}A universal remote
Pressing "power" on a universal remote sends the same command to whichever device is connected; the TV, the speaker and the projector each respond in their own way. The remote does not need to know which device it is.
Quick check: When is the method body to execute chosen for an overridden method called through a superclass reference in Java?
- At compile time, from the reference's declared type
- At run time, from the actual object's class
- When the class is loaded
- It is chosen randomly
Answer
At run time, from the actual object's class — Dynamic dispatch selects the implementation of the object's actual class at run time.