- Java Tutorial
- Java Introduction
- Java Features
- Java Simple Program
- JVM, JDK and JRE
- Java Syntax
- Java Comments
- Java Keywords
- Java Variables
- Java Literals
- Java Separators
- Java Datatypes
- Java Operators
- Java Statements
- Java Strings
- Java Arrays
- Control Statement
- Java If
- Java If-else
- Java If-else-if
- Java Nested If
- Java Switch
- Iteration Statement
- Java For Loop
- Java For Each Loop
- Java While Loop
- Java Do While Loop
- Java Nested Loop
- Java Break/Continue
- Java Methods
- Java Methods
- Java Method Parameters
- Java Method Overloading
- Java Recursion
- Java OOPS
- Java OOPs
- Java Classes/Objects
- Java Inheritance
- Java Polymorphism
- Java Encapsulation
- Java Abstraction
- Java Modifiers
- Java Constructors
- Java Interface
- Java static keyword
- Java this keyword
- Java File Handling
- Java File
- Java Create File
- Java Read/Write File
- Java Delete File
- Java Program To
- Add Two Numbers
- Even or Odd Numbers
- Reverse a String
- Swap Two Numbers
- Prime Number
- Fibonacci Sequence
- Palindrome Strings
- Java Reference
- Java String Methods
- Java Math Methods
Java Polymorphism
The word Polymorphism comes from the Greek words "poly" (many) and "morph" (forms). In the context of Java and Object-Oriented Programming (OOP), it describes the ability of a single action or object to behave differently depending on the context. In simpler terms, it allows us to perform a single action in different ways.
Polymorphism is one of the four pillars of OOP and is crucial for creating flexible, scalable code. It allows a parent class reference to point to a child class object, enabling developers to write code that works with a generic type while executing specific behaviors at runtime.
Compile-Time Polymorphism:
Also known as Static Polymorphism, this is achieved through Method Overloading. This occurs when a class has multiple methods with the same name but different parameters (different types, different number of arguments, or both).
The Java compiler determines which method to call at the time of compilation based on the method signature provided.
class Calculator {
// Overloaded method for two integers
int add(int num1, int num2) {
return num1 + num2;
}
// Overloaded method for three integers
int add(int num1, int num2, int num3) {
return num1 + num2 + num3;
}
// Overloaded method for doubles
double add(double num1, double num2) {
return num1 + num2;
}
}
In the real world, you might use overloading for a Logger class where you want to log a simple String message, or an entire Exception object, using the same method name: log(String msg) and log(Exception e).
Runtime Polymorphism:
Also known as Dynamic Polymorphism or Dynamic Method Dispatch, this is achieved through Method Overriding. This happens when a subclass provides a specific implementation of a method that is already defined in its parent class.
The decision of which method to execute is made at runtime by the Java Virtual Machine (JVM), based on the actual object being referenced, not the reference type.
class Animal {
void makeSound() {
System.out.println("The animal makes a generic sound");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("The dog barks: Woof! Woof!");
}
}
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("The cat meows: Meow!");
}
}
To see runtime polymorphism in action, consider this execution code:
public class Main {
public static void main(String[] args) {
Animal myPet = new Dog(); // Parent reference, Child object
myPet.makeSound(); // Outputs: The dog barks: Woof! Woof!
myPet = new Cat(); // Now pointing to a Cat object
myPet.makeSound(); // Outputs: The cat meows: Meow!
}
}
Animal, the compiler will only let you call methods defined in Animal. While this is true, the version of the method that runs is determined by the actual object (the Dog or Cat).
Summary
Polymorphism is a powerful tool that allows for cleaner, more maintainable code. By using Compile-Time Polymorphism, you can create intuitive APIs with methods that handle different data types. By using Runtime Polymorphism, you can write code that interacts with a general category of objects (like Shape or Employee) while allowing each specific type (like Circle or Manager) to provide its own unique behavior.
@Override annotation when overriding methods. It tells the compiler to check that you are actually overriding a method from the superclass, preventing bugs caused by simple typos in method names.
Mastering these concepts is a major step in transitioning from writing simple scripts to building robust, professional-grade Java applications.