Polymorphism in Java

by Jasleen Chhabra | Updated on 24 August 2024

Table of Contents (Click any Topic to view first)

  1. Understanding the Polymorphism in Java
  2. Method Overloading in Java
  3. Why Method Overloading is Not Possible by Changing the Return Type Only
  4. Can We Overload the Main Method?
  5. Method Overloading with Type Promotion
  6. Method Overriding in Java
  7. Can We Override Static Methods?
  8. Difference Between Method Overloading and Method Overriding

Understanding the Polymorphism in Java

Polymorphism is a fundamental concept in Java that allows methods to perform different tasks based on the object that is invoking them. It enhances flexibility and integration in the code, enabling objects to be treated as instances of their parent class rather than their actual class.

Method Overloading in Java

Method overloading in Java allows a class to have more than one method with the same name, provided their parameter lists differ. It is a way to achieve polymorphism, making the code more readable and reusable.

Different Ways to Overload a Method

  1. By Changing the Number of Arguments:

You can overload methods by varying the number of parameters.

class Adder { 

    static int add(int a, int b) { return a + b; } 

    static int add(int a, int b, int c) { return a + b + c; } 

class TestOverloading1 { 

    public static void main(String[] args) { 

        System.out.println(Adder.add(11, 11)); 

        System.out.println(Adder.add(11, 11, 11)); 

    } 

}

  1. By Changing the Data Type of Arguments:

You can overload methods by changing the data type of the parameters.

class Adder { 

    static int add(int a, int b) { return a + b; } 

    static double add(double a, double b) { return a + b; } 

class TestOverloading2 { 

    public static void main(String[] args) { 

        System.out.println(Adder.add(11, 11)); 

        System.out.println(Adder.add(12.3, 12.6)); 

    } 

}

Why Method Overloading is Not Possible by Changing the Return Type Only

Method overloading cannot be achieved by merely changing the return type of the method. This is because the return type alone is not sufficient to distinguish between two methods. The Java compiler will not be able to resolve the call to the appropriate method based on return type alone, leading to ambiguity.

Example illustrating the ambiguity:

class Adder { 

    static int add(int a, int b) { return a + b; } 

    static double add(int a, int b) { return a + b; } 

class TestOverloading3 { 

    public static void main(String[] args) { 

        System.out.println(Adder.add(11, 11)); // Compiler error: method add(int,int) is already defined in class Adder

    } 

}

Can We Overload the Main Method?

Yes, we can overload the main method in Java. However, the JVM calls the main method with the signature public static void main(String[] args). Other overloaded main methods can exist but will not be used as the entry point for the application.

Example of overloading the main method:

class TestOverloading4 { 

    public static void main(String[] args) { System.out.println("main with String[]"); } 

    public static void main(String args) { System.out.println("main with String"); } 

    public static void main() { System.out.println("main without args"); } 

}

Output:

main with String[]

Method Overloading with Type Promotion

When there is no exact match for the arguments, type promotion is performed. For example, byte can be promoted to short, int, long, float, or double.

Example of Type Promotion:

class OverloadingCalculation1 { 

    void sum(int a, long b) { System.out.println(a + b); } 

    void sum(int a, int b, int c) { System.out.println(a + b + c); } 

    

    public static void main(String[] args) { 

        OverloadingCalculation1 obj = new OverloadingCalculation1(); 

        obj.sum(20, 20); // int to long promotion  

        obj.sum(20, 20, 20); 

    } 

}

Output:

40

60

Example Where Matching Type Arguments Exist:

class OverloadingCalculation2 { 

    void sum(int a, int b) { System.out.println("int arg method invoked"); } 

    void sum(long a, long b) { System.out.println("long arg method invoked"); } 

    

    public static void main(String[] args) { 

        OverloadingCalculation2 obj = new OverloadingCalculation2(); 

        obj.sum(20, 20); // exact match found for int arguments  

    } 

}

Output:

int arg method invoked

Example of Ambiguity Due to Type Promotion:

class OverloadingCalculation3 { 

    void sum(int a, long b) { System.out.println("a method invoked"); } 

    void sum(long a, int b) { System.out.println("b method invoked"); } 

    

    public static void main(String[] args) { 

        OverloadingCalculation3 obj = new OverloadingCalculation3(); 

        obj.sum(20, 20); // ambiguous due to type promotion  

    } 

}

Output:

Compile Time Error

In summary, method overloading enhances code readability and reusability by allowing multiple methods with the same name but different parameter lists. It is an essential feature of Java's polymorphism, offering flexibility in method implementation.


Method Overriding in Java

Method overriding in Java is when a subclass (child class) provides a specific implementation for a method that is already defined in its superclass (parent class). The method in the subclass must have the same name and parameters as the one in the superclass. This allows the child class to offer a specific behavior while still maintaining the general behavior defined by the parent class.

Usage of Method Overriding

  • Specific Implementation: It allows a subclass to provide a specific implementation of a method that is already defined in its superclass.
  • Runtime Polymorphism: Method overriding is used to achieve runtime polymorphism, allowing the program to decide at runtime which method to call based on the object type.

Rules for Method Overriding

  • The method in the child class must have the same name and parameters as the method in the parent class.
  • There must be an inheritance relationship (IS-A relationship) between the parent and child classes.

Understanding the Problem Without Method Overriding

Without method overriding, you would not be able to provide specific implementations in subclasses, leading to less flexible and reusable code.

Example Without Overriding:

class Vehicle {

  void run() {

    System.out.println("Vehicle is running");

  }

}

 

class Bike extends Vehicle {

  public static void main(String args[]) {

    Bike obj = new Bike();

    obj.run();

  }

}

Output:

Vehicle is running

In the above example, the Bike class inherits the run method from Vehicle, but cannot provide its specific implementation.

Example of Method Overriding

Example With Overriding:

class Vehicle {

  void run() {

    System.out.println("Vehicle is running");

  }

}

 

class Bike2 extends Vehicle {

  @Override

  void run() {

    System.out.println("Bike is running safely");

  }

 

  public static void main(String args[]) {

    Bike2 obj = new Bike2();

    obj.run();

  }

}

Output:

Bike is running safely

Here, the Bike2 class overrides the run method from Vehicle, providing its specific implementation.

Real Example of Java Method Overriding

Consider a scenario where different banks provide different rates of interest. Method overriding allows each bank to define its rate of interest while maintaining a common interface.

Example:

class Bank {

  int getRateOfInterest() {

    return 0;

  }

}

 

class SBI extends Bank {

  @Override

  int getRateOfInterest() {

    return 8;

  }

}

 

class ICICI extends Bank {

  @Override

  int getRateOfInterest() {

    return 7;

  }

}

 

class AXIS extends Bank {

  @Override

  int getRateOfInterest() {

    return 9;

  }

}

 

class Test2 {

  public static void main(String args[]) {

    SBI s = new SBI();

    ICICI i = new ICICI();

    AXIS a = new AXIS();

    System.out.println("SBI Rate of Interest: " + s.getRateOfInterest());

    System.out.println("ICICI Rate of Interest: " + i.getRateOfInterest());

    System.out.println("AXIS Rate of Interest: " + a.getRateOfInterest());

  }

}

Output:

SBI Rate of Interest: 8

ICICI Rate of Interest: 7

AXIS Rate of Interest: 9


Can We Override Static Methods?

No, static methods cannot be overridden. This is because static methods are bound to the class, not to instances of the class. Method overriding requires an instance method that is bound to an object.

Reason: Static methods belong to the class area, whereas instance methods belong to the heap area. The binding of static methods occurs at compile time (static binding), while the binding of instance methods occurs at runtime (dynamic binding).

Difference Between Method Overloading and Method Overriding

  • Method Overloading: Occurs within the same class and involves multiple methods with the same name but different parameters (type or number of parameters).
  • Method Overriding: Involves a subclass redefining a method that is already defined in its superclass with the same name and parameters.

Conclusion: 

Polymorphism is a pivotal feature in Java, providing flexibility and enhancing code maintainability. It allows methods to perform different tasks based on the object invoking them, thus enabling a more modular and scalable approach to programming.

Key Takeaways:

  1. Method Overloading:
    • Definition: Allows a class to have multiple methods with the same name but different parameters.
    • Benefits: Enhances code readability and reusability, facilitating flexible method implementation.
    • Usage: Achieved by changing the number or type of parameters, not just the return type.
  2. Method Overriding:
    • Definition: Enables a subclass to provide a specific implementation of a method already defined in its superclass.
    • Benefits: Supports runtime polymorphism, allowing dynamic method dispatch based on object type.
    • Usage: Requires an inheritance relationship and identical method signatures in both superclass and subclass.
  3. Polymorphism in Action:
    • Compile-time Polymorphism: Achieved through method overloading.
    • Runtime Polymorphism: Achieved through method overriding.
  4. Limitations and Rules:
    • Static Methods: Cannot be overridden due to their binding at compile time.
    • Ambiguity in Overloading: Must avoid ambiguous method calls, especially with type promotion.

Understanding and leveraging polymorphism through method overloading and overriding enables developers to write more efficient, maintainable, and flexible code. It is fundamental to mastering object-oriented programming in Java, promoting code reusability, and supporting the development of robust applications.



FAQ

Any Questions?
Look Here.

Related Articles

Abstraction in Java

Binding in Java

Break Statement in Java

Classes & Objects in Java

Collections Framework in Java

Comments in Java

Continue Statement in Java

Control Statements in Java

Data Types in Java

Do While-Loop in Java

Encapsulation in Java

Exception Handling in Java

For-Loop In Java

Hello World Program in Java

If-else Statement in Java

Inheritance in Java

Introduction to Java

Java Database Connectivity (JDBC)

Java Development Tools and Frameworks

Java GUI (Graphical User Interface) Programming

Java I/O

Java Vs. C++

Methods and Constructors in Java

Multithreading in Java

Object Oriented Programming in Java

Operators in Java

Scanner Class in Java

Setting Up Java Environment

Static Keyword in Java

Super Keyword in Java

Switch Statement in Java

This Keyword in Java

Variables in Java

While-Loop in Java