Runtime Polymorphism — Parent Reference to Child Object
Fast recall
Quick revision
Core answer
Animal a = new Dog(), the compile-time type Animal controls which members the expression may access and participates in overload resolution. For an overridable instance method such as speak(), runtime dispatch selects Dog's override. Fields, static methods, private methods, constructors, and explicit super calls are not dynamically dispatched this way.Deep understanding of how the JVM resolves method calls at runtime vs compile time
Thinking the reference type determines which method runs — it only determines which methods are visible; the object type determines execution
Explain the practical benefit: you can write code against the Animal type and it works correctly for all subclasses without modification — the Open/Closed Principle
Interview-ready guide
Interview answer
The key mental model is that Animal a = new Dog() puts two types in play, and they do completely different jobs.
The reference type — Animal — is what the compiler checks. It's a gatekeeper for what you're allowed to call: if Animal has speak(), you can call it; if you try a Dog-only method like wagTail(), it won't compile, even though the real object is a Dog.
The object type — Dog — is what the JVM cares about when the program actually runs. At that point it ignores the declared type, looks at the real object in memory, finds Dog's speak(), and runs it, so you get 'Woof!' and not the Animal version. That runtime lookup is dynamic method dispatch, and the JVM does it through a vtable per class.
Why it matters in real code: you can write one method that takes an Animal, call speak() inside it, and pass it any animal you ever create — no instanceof, no if-else chains, and you never touch that method again when you add a new subclass. That's the Open/Closed Principle in practice. The mistake I'd be careful to avoid is saying the reference type picks the method — it doesn't, it only controls visibility. And a detail that usually impresses: dynamic dispatch applies to methods only — fields are resolved by the reference type, so fields are not polymorphic.
Runtime Polymorphism — Parent Reference to Child Object
Direct Answer
With Animal a = new Dog(), the compile-time type Animal controls which members the expression may access and participates in overload resolution. For an overridable instance method such as speak(), runtime dispatch selects Dog's override. Fields, static methods, private methods, constructors, and explicit super calls are not dynamically dispatched this way.
Code Example
class Animal {
void speak() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
@Override
void speak() { System.out.println("Woof!"); }
}
class Cat extends Animal {
@Override
void speak() { System.out.println("Meow!"); }
}
public class RuntimePolymorphismDemo {
// This method accepts ANY Animal — it doesn't care about the actual subtype
static void makeAnimalSpeak(Animal a) {
a.speak(); // JVM dispatches to the actual object's speak() at runtime
}
public static void main(String[] args) {
Animal a1 = new Dog(); // Animal reference → Dog object
Animal a2 = new Cat(); // Animal reference → Cat object
Animal a3 = new Animal(); // Animal reference → Animal object
a1.speak(); // Output: Woof! ← JVM found Dog.speak()
a2.speak(); // Output: Meow! ← JVM found Cat.speak()
a3.speak(); // Output: Some generic animal sound
System.out.println("--- via helper method ---");
makeAnimalSpeak(new Dog()); // Output: Woof!
makeAnimalSpeak(new Cat()); // Output: Meow!
// makeAnimalSpeak never changes when you add Snake, Bird, etc.
// Compile-time restriction: reference type controls visibility
// a1.wagTail(); // COMPILE ERROR — Animal has no wagTail()
}
}
// Output:
// Woof!
// Meow!
// Some generic animal sound
// --- via helper method ---
// Woof!
// Meow!
Common Mistakes & Pitfalls
- Believing the reference type decides which method runs — it only controls visibility; the runtime class selects an override for eligible instance methods. This is the heart of the question and the most common wrong answer.
- Trying to call child-only methods through a parent reference —
Animal a = new Dog(); a.wagTail();won't compile; you must cast toDogfirst. - Assuming fields are polymorphic too — eligible overridden instance methods are dispatched dynamically; field access uses the reference type, so
a.namereadsAnimal's field even when the object is aDog. - Confusing this with overloading — overloading is chosen by the compiler from argument types; this dispatch is chosen by the JVM from the real object at runtime.
Check your understanding
Answer these without looking back at the article.
- How do you call a subclass-specific method through a parent reference?
- What is the instanceof operator used for?
- What is a virtual method table (vtable) in Java?
Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.