Java Polymorphism
Introduced in 2026-03-12-object-oriented-programming-ii (Lecture, Week 3).
What is polymorphism?
From the Greek “poly” (many) and “morphe” (form). In programming, it allows the same method call to produce different behaviour depending on the object that executes it.
Compile-time polymorphism (method overloading)
Multiple methods share a name but differ in parameter list (type, number, or both). Which one runs is decided at compile time, based on the method signature (see java-encapsulation#method-signatures):
public class CompPolymorphism {
static String print(int value) { return "number"; }
static String print(String value) { return "text"; }
public static void main(String[] args) {
System.out.println(print(21)); // "number"
System.out.println(print("21")); // "text"
}
}Runtime polymorphism (dynamic method dispatch)
Also called dynamic method dispatch. The method that gets executed is determined at runtime, based on the object’s actual type, not the variable’s declared type — implemented through method overriding (see java-inheritance):
The subclass’s overriding method executes, regardless of the compile-time type of the subclass instance. — Effective Java
public class Animal {
public void makeSound() { System.out.println("Animal makes a sound"); }
}
public class Cat extends Animal {
@Override public void makeSound() { System.out.println("Cat meows"); }
}
public class Dog extends Animal {
@Override public void makeSound() { System.out.println("Dog barks"); }
}
Animal myAnimal = new Dog();
myAnimal.makeSound(); // "Dog barks" — even though the variable's type is AnimalSubtype polymorphism
Objects of different subclasses can be treated as objects of a common superclass or interface, since subclasses are subtypes of their superclass. Achieved through inheritance (extends) or interface implementation (implements) — code works with the abstraction (supertype) rather than a specific implementation:
public static void performAnimalSound(Animal animal) {
animal.makeSound();
}
performAnimalSound(new Dog()); // "Dog barks"
performAnimalSound(new Cat()); // "Cat meows"The same works via an interface instead of a shared superclass:
public interface Animal { void makeSound(); }
public class Cat implements Animal { ... }
public class Dog implements Animal { ... }
// Can pass any class that implements the interface
performAnimalSound(new Dog());
performAnimalSound(new Cat());