← Back to Core Java Course | Chapter 9: OOP Advanced | Lesson 1 of 8

Java Polymorphism

What is Polymorphism?

Polymorphism ('many forms') lets objects of different classes be treated through a shared, common interface or parent type, so the same line of calling code can correctly trigger different behavior depending on which actual object it's operating on.

Example: What is Polymorphism?

java
class Animal {
	void sound() { System.out.println("Some sound"); }
}
class Dog extends Animal {
	@Override
	void sound() { System.out.println("Bark"); }
}
public class Main {
	public static void main(String[] args) {
		Animal a = new Dog();
		a.sound(); // same call, different behavior depending on the object
	}
}

Compile-Time Polymorphism

Compile-time polymorphism, achieved through method overloading, lets a class define several methods sharing one name but differing in their parameter lists — the compiler picks the correct version to call based on the arguments' types at compile time.

Example: Compile-Time Polymorphism

java
public class Main {
	static int add(int a, int b) { return a + b; }
	static double add(double a, double b) { return a + b; }
	public static void main(String[] args) {
		System.out.println(add(2, 3));
		System.out.println(add(2.5, 3.5));
	}
}

Run-Time Polymorphism

Run-time polymorphism is achieved through method overriding, and the decision about which overridden method actually runs is made by the JVM at runtime based on the object's real, concrete class — not by the compiler based on the reference variable's declared type.

Example: Run-Time Polymorphism

java
class Animal {
	void sound() { System.out.println("Some sound"); }
}
class Dog extends Animal {
	@Override
	void sound() { System.out.println("Bark"); }
}
public class Main {
	public static void main(String[] args) {
		Animal a = new Dog();
		a.sound(); // decided at runtime by the object's real class
	}
}

Polymorphism with Data Members

Only methods participate in dynamic runtime dispatch in Java; fields do not — if a subclass hides a parent's field with one of the same name, which field you get back depends on the reference type at compile time, not the object's actual runtime class.

Example: Polymorphism with Data Members

java
class Animal {
	String type = "Animal";
}
class Dog extends Animal {
	String type = "Dog";
}
public class Main {
	public static void main(String[] args) {
		Animal a = new Dog();
		System.out.println(a.type); // "Animal": fields don't use dynamic dispatch
	}
}

Benefits of Polymorphism

Polymorphism promotes loose coupling by letting you write functions and methods that accept a general parent type and work correctly with any subclass passed in, without needing to know in advance every possible subclass that might eventually exist.

Example: Benefits of Polymorphism

java
class Animal {
	void sound() { System.out.println("Some sound"); }
}
class Dog extends Animal {
	@Override
	void sound() { System.out.println("Bark"); }
}
class Cat extends Animal {
	@Override
	void sound() { System.out.println("Meow"); }
}
public class Main {
	static void makeSound(Animal a) { // works with any subclass
		a.sound();
	}
	public static void main(String[] args) {
		makeSound(new Dog());
		makeSound(new Cat());
	}
}
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.