Java Polymorphism
What is Polymorphism?
Polymorphism means "many forms." In Java, the same method name can behave differently depending on the context. There are two types:
| Type | Also Called | Resolved At | Mechanism |
|---|---|---|---|
| Compile-time polymorphism | Static binding | Compile time | Method overloading |
| Runtime polymorphism | Dynamic binding | Runtime | Method overriding + upcasting |
Compile-time Polymorphism (Overloading)
public class Overloading {
// Same method name, different parameter types/count
public static void print(int n) {
System.out.println("int: " + n);
}
public static void print(double d) {
System.out.println("double: " + d);
}
public static void print(String s) {
System.out.println("String: " + s);
}
public static void print(int a, int b) {
System.out.println("two ints: " + a + ", " + b);
}
public static void main(String[] args) {
print(42); // int: 42
print(3.14); // double: 3.14
print("Hello"); // String: Hello
print(1, 2); // two ints: 1, 2
// The compiler picks the right version at compile time
}
}
Runtime Polymorphism (Dynamic Dispatch)
When a parent-type reference holds a child object (upcasting), the JVM decides at runtime which overridden method to call. This is called dynamic method dispatch.
class Shape {
public void draw() {
System.out.println("Drawing a shape.");
}
}
class Circle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a circle.");
}
}
class Rectangle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a rectangle.");
}
}
class Triangle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a triangle.");
}
}
public class RuntimePoly {
public static void main(String[] args) {
// Upcasting — parent reference, child object
Shape s1 = new Circle();
Shape s2 = new Rectangle();
Shape s3 = new Triangle();
// JVM calls the correct overridden method at runtime
s1.draw(); // Drawing a circle.
s2.draw(); // Drawing a rectangle.
s3.draw(); // Drawing a triangle.
// Polymorphic array
Shape[] shapes = { new Circle(), new Rectangle(), new Triangle() };
for (Shape s : shapes) {
s.draw(); // dynamic dispatch
// instanceof check before downcasting
if (s instanceof Circle c) {
System.out.println(" -> This is a Circle");
}
}
}
}
Ready to Level Up Your Skills?
Explore 500+ free tutorials across 20+ languages and frameworks.