Java · Chapter 27 of 42

Java Polymorphism

Polymorphism means 'many forms' — the ability for the same method call to behave differently depending on the object it's called on. Java achieves this through method overriding (runtime polymorphism) and method overloading (compile-time polymorphism).

A superclass reference can point to a subclass object, and calling an overridden method invokes the subclass's version — this is central to flexible, extensible OOP designs.

Syntax
class Sub extends Super {
  @Override
  void method() { }
}

Method overriding

A subclass provides its own implementation of a method already defined in its superclass, using the same signature and the @Override annotation.

Runtime polymorphism in action

When a superclass-typed variable holds a subclass object, calling an overridden method executes the subclass's version at runtime, not the superclass's.

Example 1 (java)
class Animal {
  void sound() { System.out.println("Some sound"); }
}
class Cat extends Animal {
  @Override
  void sound() { System.out.println("Meow"); }
}
public class Main {
  public static void main(String[] args) {
    Animal a = new Cat();
    a.sound();
  }
}
Output
Meow

Even though a is typed as Animal, it holds a Cat object, so the overridden sound() runs.

Key points

  • Polymorphism lets the same call behave differently per object type.
  • Overriding is resolved at runtime based on the actual object type.
  • Overloading is resolved at compile time based on arguments.
  • @Override helps catch mistakes when overriding methods.
💡 Note: Polymorphism enables writing flexible code that works with superclass types but adapts to subclass behavior.

📝 Quick Quiz

1. What is resolved at runtime in Java?

2. What annotation helps verify correct overriding?

3. If Animal a = new Cat(); and sound() is overridden, whose version runs?