Polymorphism in Java is one of the core concepts in object-oriented programming (OOP) that allows objects to behave differently based on their specific class type. The word polymorphism means having many forms, and it comes from the Greek words poly (many) and morph (forms). This means one entity can take many forms.
- Multiple Behaviors: The same method can behave differently depending on the object that calls this method.
- Method Overriding: A child class can redefine a method of its parent class.
- Method Overloading: We can define multiple methods with the same name but different parameters.
- Runtime Decision: At runtime, Java determines which method to call depending on the object's actual class.
Real-Life Illustration of Polymorphism
Consider a person who plays different roles in life, like a father, a husband, and an employee. Each of these roles defines different behaviors of the person depending on the object calling it.
// Base class Person
class Person {
// Method that displays the
// role of a person
void role() {
System.out.println("I am a person.");
}
}
// Derived class Father that
// overrides the role method
class Father extends Person {
// Overridden method to show
// the role of a father
@Override
void role() {
System.out.println("I am a father.");
}
}
public class Main {
public static void main(String[] args) {
// Creating a reference of type Person
// but initializing it with Father class object
Person p = new Father();
// Calling the role method. It calls the
// overridden version in Father class
p.role();
}
}
Output
I am a father.
Explanation: In the above example, the Person class has a method role() that prints a general message. The Father class overrides role() to print a specific message. The reference of type Person is used to point to an object of type Father, demonstrating polymorphism at runtime. The overridden method in Father is invoked when role() is called.
Types of Polymorphism in Java
In Java Polymorphism is mainly divided into two types:

1. Compile-Time Polymorphism
Compile-Time Polymorphism in Java is also known as static polymorphism and also known as method overloading. This happens when multiple methods in the same class have the same name but different parameters.
Method Overloading
Method overloading means defining multiple methods with the same name but different parameter lists. The method call is resolved at compile time based on the arguments passed.
Example: Method overloading by changing the number of arguments
// Class 1
// Helper class
class Helper {
// Method with 2 integer parameters
static int Multiply(int a, int b)
{
// Returns product of integer numbers
return a * b;
}
// Method 2
// With same name but with 2 double parameters
static double Multiply(double a, double b)
{
// Returns product of double numbers
return a * b;
}
}
// Class 2
// Main class
class Geeks
{
// Main driver method
public static void main(String[] args) {
// Calling method by passing
// input as in arguments
System.out.println(Helper.Multiply(2, 4));
System.out.println(Helper.Multiply(5.5, 6.3));
}
}
Output
8 34.65
Explanation: The Multiply method is overloaded with different parameter types. The compiler picks the correct method during compile time based on the arguments.
2. Runtime Polymorphism
Runtime Polymorphism in Java is also known as dynamic method dispatch. It occurs when a method call is resolved at runtime, and it is achieved using method overriding.
Method Overriding
Method overriding occurs when a subclass provides its own implementation of a method already defined in its superclass. The method must have the same name, parameters, and return type.
Note: At runtime, the method that gets executed depends on the actual object type, not the reference type.
Example: This program demonstrates method overriding in Java, where the Print() method is redefined in the subclasses (subclass1 and subclass2) to provide specific implementations.
// Class 1
// Helper class
class Parent {
// Method of parent class
void Print() {
System.out.println("parent class");
}
}
// Class 2
// Helper class
class subclass1 extends Parent {
// Method
void Print() {
System.out.println("subclass1");
}
}
// Class 3
// Helper class
class subclass2 extends Parent {
// Method
void Print() {
System.out.println("subclass2");
}
}
// Class 4
// Main class
class Geeks {
// Main driver method
public static void main(String[] args) {
// Creating object of class 1
Parent a;
// Now we will be calling print methods
// inside main() method
a = new subclass1();
a.Print();
a = new subclass2();
a.Print();
}
}
Output
subclass1 subclass2
Explanation: In the above example, when an object of a child class is created, then the method inside the child class is called. This is because the method in the parent class is overridden by the child class. This method has more priority than the parent method inside the child class. So, the body inside the child class is executed.
Advantages of Polymorphism
- Code Reusability: The same method or class works with different object types.
- Flexibility: Different objects can be treated as a common superclass type.
- Abstraction: Enables working with general types (abstract classes or interfaces) instead of concrete classes.
- Dynamic Behavior: Method calls are resolved at runtime based on the actual object type.
Disadvantages of Polymorphism
- It can make more difficult to understand the behavior of an object.
- This may cause performance issues, as polymorphic behavior may require additional computations at runtime.
