In this tutorial, you’ll learn everything about Polymorphism in Java — one of the core principles of Object-Oriented Programming (OOP). You’ll see what polymorphism is, why it’s useful, and how it’s applied in real-world scenarios along with 10 interview questions and coding examples.
1. What is Polymorphism in Java?
Polymorphism means “many forms.” It allows one object to behave differently based on the context.
In simple words, polymorphism allows us to perform a single action in different ways.
For example, the same method name draw() can be used by multiple shapes like Circle, Rectangle, and Triangle — each implementing its own version of draw().
2. Types of Polymorphism
2.1 Compile-Time Polymorphism (Static Binding)
This type of polymorphism is achieved by method overloading — when multiple methods have the same name but different parameters.
class MathOperation {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
}
public class Main {
public static void main(String[] args) {
MathOperation m = new MathOperation();
System.out.println(m.add(2, 3)); // calls int version
System.out.println(m.add(2.5, 3.5)); // calls double version
}
}
Here, Java decides which method to call at compile time.
2.2 Runtime Polymorphism (Dynamic Binding)
This is achieved through method overriding — when a subclass provides its own implementation of a method already defined in its parent class.
class Animal {
void sound() {
System.out.println("Animal makes sound");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
}
}
public class Main {
public static void main(String[] args) {
Animal a = new Dog();
a.sound(); // Output: Dog barks
}
}
Here, the method call is determined at runtime depending on the actual object type.
3. Why Polymorphism is Useful
- Flexibility: You can write code that works with parent classes and automatically use subclass behavior.
- Extensibility: Add new features or classes without changing existing code.
- Clean Design: Promotes loose coupling and improves scalability.
4. Real-Life Example
Imagine an online payment system where different payment methods can be used but all follow the same structure:
class Payment {
void pay() {
System.out.println("Generic payment");
}
}
class CreditCardPayment extends Payment {
void pay() {
System.out.println("Payment via Credit Card");
}
}
class UpiPayment extends Payment {
void pay() {
System.out.println("Payment via UPI");
}
}
public class TestPayment {
public static void main(String[] args) {
Payment p;
p = new CreditCardPayment();
p.pay(); // Payment via Credit Card
p = new UpiPayment();
p.pay(); // Payment via UPI
}
}
5. 10 Scenario-Based Interview Questions and Answers
Q1. What is the difference between method overloading and overriding?
Overloading: Happens at compile-time, same name but different parameters.
Overriding: Happens at runtime, same name and parameters but in subclass.
Q2. Can you override a static method?
No. Static methods are class-level, not object-level. They can only be hidden, not overridden.
Q3. Can constructors be overridden?
No. Constructors are not inherited, hence they cannot be overridden.
Q4. What happens if you call an overridden method from a superclass constructor?
The subclass method gets called, but it’s risky because the subclass is not fully initialized yet.
Q5. Why can’t polymorphism be achieved with variables?
Because variables are resolved at compile-time, not at runtime.
Q6. How is runtime polymorphism implemented internally?
Through a mechanism called dynamic method dispatch using a vtable (virtual method table).
Q7. What is upcasting and downcasting?
- Upcasting: Assigning a child object to a parent reference (
Animal a = new Dog();). - Downcasting: Casting back to child type (
Dog d = (Dog) a;).
Q8. Can polymorphism work without inheritance?
No. Polymorphism requires inheritance or interfaces to define multiple forms.
Q9. What is the role of the @Override annotation?
It ensures that a method truly overrides a parent method, providing compile-time checking.
Q10. How does interface polymorphism work?
interface Shape { void draw(); }
class Circle implements Shape {
public void draw() { System.out.println("Drawing Circle"); }
}
class Square implements Shape {
public void draw() { System.out.println("Drawing Square"); }
}
public class Test {
public static void main(String[] args) {
Shape s = new Circle();
s.draw(); // Drawing Circle
s = new Square();
s.draw(); // Drawing Square
}
}
6. Coding Examples
Example 1: Vehicle Start Example
class Vehicle {
void start() {
System.out.println("Vehicle is starting");
}
}
class Car extends Vehicle {
void start() {
System.out.println("Car starts with key");
}
}
class Bike extends Vehicle {
void start() {
System.out.println("Bike starts with button");
}
}
public class Main {
public static void main(String[] args) {
Vehicle v1 = new Car();
Vehicle v2 = new Bike();
v1.start(); // Car starts with key
v2.start(); // Bike starts with button
}
}
Example 2: Find the Output
class A {
void show() { System.out.println("A"); }
}
class B extends A {
void show() { System.out.println("B"); }
}
class C extends B {
void show() { System.out.println("C"); }
}
public class Test {
public static void main(String[] args) {
A obj = new C();
obj.show(); // Output: C
}
}
Example 3: Interface-Based Polymorphism
interface PaymentGateway {
void pay();
}
class Paytm implements PaymentGateway {
public void pay() { System.out.println("Payment via Paytm"); }
}
class GooglePay implements PaymentGateway {
public void pay() { System.out.println("Payment via GooglePay"); }
}
public class TestPayment {
public static void main(String[] args) {
PaymentGateway pg = new GooglePay();
pg.pay();
pg = new Paytm();
pg.pay();
}
}
Example 4: Static Method Trick
class Parent {
static void show() { System.out.println("Parent"); }
}
class Child extends Parent {
static void show() { System.out.println("Child"); }
}
public class Test {
public static void main(String[] args) {
Parent p = new Child();
p.show(); // Output: Parent
}
}
Explanation: Static methods are not polymorphic; they are resolved by class reference, not object type.
Example 5: Abstract Class Example
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
void draw() {
System.out.println("Drawing Circle");
}
}
class Rectangle extends Shape {
void draw() {
System.out.println("Drawing Rectangle");
}
}
public class Main {
public static void main(String[] args) {
Shape s = new Circle();
s.draw();
s = new Rectangle();
s.draw();
}
}
7. Summary Table
| Type | Achieved By | Binding Time | Example |
|---|---|---|---|
| Compile-Time | Method Overloading | Compile Time | add(int, int) vs add(double, double) |
| Runtime | Method Overriding | Runtime | Animal a = new Dog(); a.sound(); |
Conclusion
Polymorphism makes Java code reusable, flexible, and easy to maintain. It allows developers to handle different objects in a uniform way and adds great power to object-oriented design.
Whenever you see “one interface, many implementations”, that’s polymorphism in action!
Next Step: Learn about Abstract Classes in Java to understand how polymorphism and abstraction work together in real-world applications.
0 Comments