In this tutorial, you will learn about polymorphism in Java, including compile-time polymorphism through method overloading and runtime polymorphism through method overriding, with simple Java examples.

Polymorphism in Java: meaning, purpose, and forms

Polymorphism in Java is an object-oriented programming concept where the same method name, variable reference, or interface type can work with different forms of objects. The word comes from poly, meaning many, and morph, meaning form.

In practical Java programs, polymorphism helps you write code that depends on a general type, such as a superclass or interface, while the actual object can be a more specific subclass. Oracle’s Java tutorial describes this as the ability of a subclass object to be treated as an object of its superclass type: Polymorphism in the Java Tutorials.

Polymorphism in Java is commonly seen in two forms:

  • Method overloading – compile-time polymorphism, where multiple methods have the same name but different parameter lists.
  • Method overriding – runtime polymorphism, where a subclass provides its own implementation of a method already defined in the superclass.

Following picture gives a basic difference between overloading and overriding in Java.

Polymorphism in Java

You may refer Method Overloading in Java to understand what Overloading is in detail.

You may also refer Method Overriding in Java to understand what Overriding is in detail.

Method overloading in Java: compile-time polymorphism

Method overloading in Java happens when a class contains two or more methods with the same name but different parameter lists. The difference may be in the number of parameters, the types of parameters, or the order of parameter types.

The compiler chooses the matching overloaded method during compilation. Because the decision is made before the program runs, overloading is also called compile-time polymorphism, static binding, or early binding.

In this example, we have two methods with the same name printer, but with different sets of parameters. The first printer() method accepts two String arguments, while the second printer() method accepts only one String argument. In the main() method, we call printer() with different numbers of arguments, and the compiler resolves the correct method based on the arguments passed.

Messenger.java

</>
Copy
package com.tutorialkart.java;

/**
 * @author tutorialkart
 */
public class Messenger {

	public static void main(String[] args) {
		Messenger msngr = new Messenger();
		msngr.printer("Bring me two trays of eggs.", "Room-mate");
		msngr.printer("Good Morning India.");
	}
	
	public void printer(String message,String sender){
		System.out.println(sender + " : " + message);
	}
	
	public void printer(String message){
		System.out.println("Broadcast message : " + message);
	}
}

Run the above Java program. Output to the console should be as shown below.

Room-mate : Bring me two trays of eggs.
Broadcast message : Good Morning India.

A return type alone cannot overload a Java method. The parameter list must be different. For example, the following two method declarations cannot exist together in the same class because their parameter lists are identical.

</>
Copy
int add(int a, int b)
double add(int a, int b)

For a valid overloaded pair, change the parameter list.

</>
Copy
int add(int a, int b)
double add(double a, double b)

Method overriding in Java: runtime polymorphism

Method overriding in Java happens when a subclass provides a specific implementation for a method that is already defined in its superclass. The method name, parameter list, and compatible return type must match the inherited method.

In overriding, the method call is resolved at runtime based on the actual object being referred to, not only the reference variable type. This is why overriding is also called runtime polymorphism, dynamic binding, or late binding.

In this example, we have super class Car.java with method run(). And there is a child class Jaguar.java with method run(). When an object of type Car is created with reference to Jaguar (Car c = new Jaguar();), invoking run method on object “c”, would execute run method in Jaguar. All this is done during run time.

OverridingExample.java

</>
Copy
package com.tutorialkart.java;

/**
 * @author tutorialkart
 */
class Car{
	public void run(){
		System.out.println("Car is running.");
	}
}

class Jaguar extends Car{
	public void run(){
		System.out.println("Jaguar is running.");
	}
}

public class OverridingExample {
	public static void main(String[] args) {
		Car c = new Jaguar();
		c.run();
	}
}

Run the above program and you shall get the output to the console as shown below.

Jaguar is running.

When writing production code, it is a good practice to use @Override above an overridden method. The annotation helps the compiler detect mistakes such as a misspelled method name or a wrong parameter list.

</>
Copy
@Override
public void run() {
    System.out.println("Jaguar is running.");
}

Overloading vs overriding in Java: key differences

The following table compares overloading and overriding in Java. The first column shows the point of comparison, and the next two columns explain how Java handles that point for each form of polymorphism.

ParameterOverloadingOverriding
Resolved by CompilerJVM (Java Virtual Machine)
Resolved during Compile timeRun time
Is achieved byfunction overloading or parameter overloadingvirtual methods and references to object instances
Effect on execution timeResolved once during compilationResolved dynamically when the method is called on an object
Other namesEarly binding (or) Static bindingLate binding (or) Dynamic binding

A more practical way to remember the difference is this: overloading is about how a method is called, while overriding is about which object’s implementation runs.

QuestionMethod overloadingMethod overriding
Can it happen inside one class?Yes. A single class can contain overloaded methods.No. It requires inheritance between a superclass and subclass.
Can parameter types be different?Yes. Different parameters are required.No. The overriding method must match the inherited method parameter list.
Can static methods participate?Yes, static methods can be overloaded.Static methods are hidden, not overridden in the runtime-polymorphism sense.
Which type matters most?The argument types used in the method call.The actual object created at runtime.

Polymorphic references in Java and dynamic method dispatch

A common use of Java polymorphism is assigning a subclass object to a superclass or interface reference. This allows the same variable type to point to different object implementations.

</>
Copy
interface Payment {
    void pay(int amount);
}

class CardPayment implements Payment {
    public void pay(int amount) {
        System.out.println("Paid " + amount + " using card.");
    }
}

class UpiPayment implements Payment {
    public void pay(int amount) {
        System.out.println("Paid " + amount + " using UPI.");
    }
}

public class PaymentExample {
    public static void main(String[] args) {
        Payment payment;

        payment = new CardPayment();
        payment.pay(500);

        payment = new UpiPayment();
        payment.pay(800);
    }
}

In the above program, the reference variable payment is of type Payment. At runtime, Java calls the pay() method of the actual object assigned to that reference.

Paid 500 using card.
Paid 800 using UPI.

This runtime selection of the correct overridden method is known as dynamic method dispatch. It is one of the main reasons polymorphism is useful in object-oriented Java design.

When polymorphism makes Java code easier to extend

Polymorphism is useful when multiple classes follow the same general contract but implement the behavior differently. Instead of writing separate code paths for every specific class, you can write code against a common superclass or interface.

  • Collections of related objects: For example, an array or list of Shape references can contain Circle, Rectangle, and Triangle objects.
  • Service implementations: An interface such as Payment can have separate implementations for card, UPI, net banking, or wallet payments.
  • Framework callbacks: Java frameworks often call overridden methods based on the actual object type provided by your application.
  • Cleaner conditional logic: Polymorphism can reduce long chains of if or switch statements when each type has its own behavior.

Common mistakes while using polymorphism in Java

  • Confusing overloading with overriding: Overloading changes the parameter list. Overriding keeps the same method signature and changes the implementation in a subclass.
  • Expecting fields to be polymorphic: Java resolves fields by reference type, not by runtime object type. Runtime polymorphism applies to instance methods.
  • Changing parameters accidentally: If a subclass method changes the parameter list, it becomes an overloaded method instead of overriding the superclass method.
  • Forgetting access rules: An overriding method cannot reduce the visibility of the inherited method. For example, a public method cannot be overridden as private.
  • Ignoring @Override: Without @Override, mistakes in method names or parameter lists can be harder to notice.

Polymorphism in Java FAQs

What is polymorphism in OOP in Java?

Polymorphism in OOP in Java is the ability to use one common type or method name with different object forms. In Java, this is mainly achieved through method overloading and method overriding.

What is polymorphism in Java with a simple example?

A simple example is a superclass reference such as Car c pointing to a subclass object such as new Jaguar(). When c.run() is called, Java executes the overridden run() method from the actual Jaguar object.

What is the purpose of polymorphism in Java?

The purpose of polymorphism in Java is to make code flexible and easier to extend. Code can work with a superclass or interface while different subclasses provide their own behavior.

Is overloading runtime polymorphism in Java?

No. Method overloading is compile-time polymorphism because the compiler selects the matching method based on the method arguments. Runtime polymorphism in Java is mainly achieved through method overriding.

Can static methods be overridden in Java polymorphism?

Static methods are not overridden in the same way instance methods are. They can be hidden by another static method in a subclass, but the call is resolved using the reference type, not by dynamic method dispatch.

Editorial QA checklist for this Java polymorphism tutorial

  • Confirm that polymorphism in Java is explained through both method overloading and method overriding.
  • Verify that the overloading example uses different parameter lists and does not imply that return type alone is enough.
  • Verify that the overriding example explains superclass reference, subclass object, and runtime method selection.
  • Check that code blocks use Java-compatible PrismJS classes and that output blocks use the output class.
  • Ensure that related Java tutorials for overloading and overriding remain linked for readers who need deeper examples.

Summary of Java polymorphism, overloading, and overriding

In this Java Tutorial, we learned that polymorphism in Java allows the same method name or reference type to work with different forms of behavior. Method overloading provides compile-time polymorphism, and method overriding provides runtime polymorphism.

Use overloading when the same operation needs different input forms. Use overriding when a subclass must provide its own behavior for a method inherited from a superclass or interface. In our next tutorial, we shall go through Method Overloading in detail.