Polymorphism in Java

Naveen AnamaneniUpdated · 5 min read

Press "play" on a phone, a laptop or a smart TV and each one plays in its own way, yet you pressed the same button. Polymorphism ("many forms") is that idea in code: one method call, many behaviors, decided by the object that receives it. It's the third pillar of OOP, and it's the reason a well-designed program can grow new features without rewriting the parts that already work.

One Call, Many Behaviors

Same call, the object decides
Alerts.java▶ Try it
public class Alerts {
    static class Notifier {
        String send(String to) { return "Generic alert to " + to; }
    }
 
    static class SmsNotifier extends Notifier {
        @Override
        String send(String to) { return "SMS to " + to; }
    }
 
    static class EmailNotifier extends Notifier {
        @Override
        String send(String to) { return "Email to " + to; }
    }
 
    static class AppNotifier extends Notifier {
        @Override
        String send(String to) { return "App push to " + to; }
    }
 
    public static void main(String[] args) {
        Notifier[] channels = {
            new SmsNotifier(), new EmailNotifier(), new AppNotifier()
        };
        String[] people = {"Navika", "Srihitha", "Advitha"};
        for (int i = 0; i < channels.length; i++) {
            System.out.println(channels[i].send(people[i]));
        }
    }
}
Output
SMS to Navika
Email to Srihitha
App push to Advitha

How it works

  1. Every element of channels has the declared type Notifier.
  2. Each element refers to a different kind of object, and each kind overrides send.
  3. The loop body is one line, channels[i].send(...), but the JVM runs the send of the actual object each time.

Try it yourself: add a WhatsAppNotifier and put one in the array. Notice that the loop doesn't change at all.

Two Kinds of Polymorphism

Compile-time polymorphismRuntime polymorphism
Achieved byMethod overloadingMethod overriding
Who decides which method runsThe compiler, from the argument typesThe JVM, from the object's actual class
Also calledStatic polymorphism, early bindingDynamic polymorphism, late binding, dynamic method dispatch
Exampleprintln(int) vs println(String)channel.send(...) above

Both get their own lessons in this chapter. When people say "polymorphism" without a qualifier, they usually mean the runtime kind.

Adding Types Without Editing Old Code

Without polymorphism, the loop above would need an if for every channel:

Without polymorphism
if (channel is SMS)        { ...send an SMS... }
else if (channel is Email) { ...send an email... }
else if (channel is App)   { ...send a push... }
// every new channel means editing this code again

With polymorphism, adding a new channel means adding a class, not editing old code. Code that works with Notifier keeps working with any notifier written in the future. This idea is the open-closed principle (see "SOLID Principles in Java"): open for extension, closed for modification.

Common Mistakes

Calling a child-only method through a parent reference. Notifier n = new SmsNotifier(); n.smsOnlyMethod(); doesn't compile. The variable's type limits what you may call (see "Upcasting and Downcasting").

Thinking fields are polymorphic. Only instance methods are. Fields and static methods follow the variable's type (see "Can Static, Private and Final Methods Be Overridden").

Using instanceof chains where an overridden method would do. If every subclass needs its own behavior, put a method in the parent and override it.

Interview Corner

What is polymorphism in Java?

Polymorphism means one interface with many implementations: the same method call behaves differently depending on the object that receives it. Java supports compile-time polymorphism through method overloading, resolved by the compiler from argument types, and runtime polymorphism through method overriding, resolved by the JVM from the object's actual class. A parent-type reference can hold any subclass object, and calls run the subclass's overriding method.

How does polymorphism help in real projects?

It lets code depend on a general type instead of specific classes. New behavior is added by writing a new subclass or interface implementation, without editing the code that uses the general type. That reduces if-else chains and keeps changes local.

Practice

  1. Easy: Create Animal with sound(), and Dog, Cat and Cow that override it. Print every sound from an Animal[] array.
  2. Harder: Create Discount with apply(double amount), and FestivalDiscount (10% off) and FlatDiscount (Rs. 200 off). Apply each to Rs. 2,000 in one loop.

Quick check: Polymorphism

4 questions
1In Notifier n = new SmsNotifier(); n.send("Navika");, whose send runs?
2Method overloading is which kind of polymorphism?
3Which is NOT polymorphic in Java?
4What does polymorphism mainly let you do?

Key Takeaways

Was this tutorial helpful?

Lesson 121 of 482