Polymorphism in Java – Master the Concept in Just 7 Mins.

To understand the concepts of polymorphism in Java, take a real-life example first.

Remember we talked about a class having different objects?

Take the example of a class Human and an object of this class named “Aaron”. Aaron is a father and has two children.

He lives with his family in Delhi and works for DataFlair. Now, imagine what Aaron is to his wife. Yes, he is her husband.

Similarly, he is a father to his two children, a neighbor to his neighbors and a coworker to anyone who works with him at DataFlair.

This is polymorphism which means multiple forms.

Stay updated with latest technology trends
Join DataFlair on Telegram!!

What is Polymorphism in Java?

Polymorphism in Java is a single method having multiple functions under the same name. A single-action gets executed in different ways.

In Java, polymorphism is of two types:

Types of Polymorphism in Java

a. Runtime polymorphism
b. Compile-time polymorphism

A java object which can pass the “IS-A” test, i.e, signifies an “is-a” relationship is an example of polymorphism.

The word polymorphism consists of two parts, “poly” signifying “many”, and “morph”, signifying “forms”.

Need for Java Polymorphism

Polymorphism allows the programmer to write code that is easy to understand. How?

Let us see the example of a class Car.

It has values like mileage and functions such as acceleration, However, a subclass, say, for example, Rolls Royce won’t be having the default acceleration value.

For a programmer to correctly define this function, he needs to rewrite the same function again.

However, polymorphism allows the programmer to use the same function name and redefine it in the child class which has a different implementation of the same method.

Compile-time polymorphism in Java

This polymorphism is static polymorphism. Operator overloading and function overloading implements this type of polymorphism.

In this type of polymorphism, the resolution of the method is done during compile time.

In the case of method overloading, we observed that the compiler resolved the method during runtime. Method overriding has compile-time polymorphism.

Operator Overloading in Java

Operator overloading is the process of overloading an operator to perform different functions.

In Java, only the plus operator is allowed to have different functions.

Let us see an example that will strengthen our ability to understand this concept.

Program to understand the Operator overloading in Java:

package com.dataflair.javapolymorphism;
public class OperatorOverload {
  public static void PlusOperator(int num1, int num2) {
    System.out.println("The plus operator can add two integers! " + (num1 + num2));

  }
  public static void PlusOperator(String str1, String str2) {
    System.out.println("The plus operator can also concatenate two strings! " + (str1 + str2));
  }
  public static void main(String[] args) {
    String str1 = "Data",
    str2 = "Flair";
    int num1 = 10,
    num2 = 14;
    PlusOperator(str1, str2);
    PlusOperator(num1, num2);
  }
}

Output:

The plus operator can also concatenate two strings! DataFlair
The plus operator can add two integers! 24

Method Overloading in Java

Method overloading is the process of having the same function name with different arguments. The compiler decides which function to call while compiling the program.

All of the functions have the same method name but they have different arguments which makes them unique.

For example, two functions namely area has the same name but one returns the area of a square and the other one returns the area of a rectangle.

Note that the square area function will have only one argument whereas the one calculating the area of a rectangle will have two arguments.

An example program to understand the concept of Method Overloading in Java:

package com.dataflair.javapolymorphism;
public class CourseOverload {
  public static int add(int num1, int num2) {
    return num1 + num2;
  }
  public static double add(double num1, double num2) {
    return num1 + num2;
  }
  public static void main(String[] args) {
    int a = 6,
    b = 90;
    double c = 12.12,
    d = 23.12;
    System.out.println(add(a, b));
    System.out.println(add(c, d));
  }

}

Output:

96
35.24

As you can see, the values are different for the same name of the function.

The compiler determines the function to call while compiling the program.

This is space-efficient and is easy to understand because the name of the function is the same. Debugging the program becomes easier.

Runtime Polymorphism in Java

Runtime polymorphism, as the name specifies, signifies dynamic resolving of the function.

Simply put, this type of polymorphism gets resolved during the execution of the program. Method overriding implements this type of polymorphism.

Program to illustrate Java runtime polymorphism of multiple inheritance:

package com.dataflair.javapolymorphism;
class Car {
  void fuel() {
    System.out.println("Can have diesel or petrol as the fuel");
  }
}
class Sedan extends Car {
  void fuel() {
    System.out.println("Shiny Car, but runs on diesel. ");
  }
}
class Engine extends Sedan {
  void fuel() {
    System.out.println("Converting diesel to smooth motion!");
  }
  public static void main(String args[]) {
    Car a1,
    a2,
    a3;
    a1 = new Car();
    a2 = new Sedan();
    a3 = new Engine();
    a1.fuel();
    a2.fuel();
    a3.fuel();
  }
}

Output:

Can have diesel or petrol as the fuel
Shiny Car, but runs on diesel.
Converting diesel to smooth motion!

There is an important point to note that data members do not override. They stay the same.

Method Overriding in Java

As the name signifies, method overriding is the process of overriding or redefining a method that was already defined in the parent class.

This is efficient and useful in many cases because a lot of the time, there is a need for redefining the function based on the class it is in.

For example, a Mercedes car, which is a subclass of the car class will have a different function named engine in comparison to the BMW car’s engine.

Program to illustrate the use of Method Overriding in Java:

package com.dataflair.javapolymorphism;
class DataFlair {
  public void coursename() {
    System.out.println("We teach a variety of courses at DataFlair!");
  }
}
class Java extends DataFlair {
  public void coursename() {
    System.out.println("Java is one of the most important courses taught at DataFlair.");
  }
}

public class MethodOverride {
  public static void main(String[] args) {
    Java course = new Java();
    course.coursename();

  }

}

Output:

Java is one of the most important courses taught at DataFlair.

Note that the definition of the course name is altered in the child class. This is method overloading.

However, if you want to execute the superclass method we can do so easily by using the super keyword.

An example is shown below:

package com.dataflair.javapolymorphism;
class DataFlair {
  public void coursename() {
    System.out.println("We teach a variety of courses at DataFlair!");
  }
}
class Java extends DataFlair {
  public void coursename() {
    super.coursename();
    System.out.println("Java is one of the most important courses taught at DataFlair.");
  }
}

public class MethodOverride {
  public static void main(String[] args) {
    Java course = new Java();

    course.coursename();

  }

}

Output:

We teach a variety of courses at DataFlair!
Java is one of the most important courses taught at DataFlair.

Binding in Java

Binding is the process of connecting the method body to the method call.

Binding in Java

There are two types of binding in Java.

a. Static Binding
b. Dynamic Binding

a. Static Binding in Java

This is the process of binding where the type of the object is determined during compile time.

Private static and final methods are statically bound during compilation.

Program to understand the concept of Static Binding in Java:

package com.dataflair.javapolymorphism;
public class StaticBinding {
  public void staticbind() {
    System.out.println("This is static binding");
  }
  public static void main(String[] args) {
    StaticBinding sb = new StaticBinding();
    sb.staticbind();
    System.out.println("Static binding occurred.");
  }
}

Output:

This is static binding
Static binding occurred.

b. Dynamic Binding in Java

Dynamic Binding is the process of determining the type of the method after compiling.

Method Overriding is essentially Dynamic Binding because the compiler decides the type of return value during execution.

Program to understand the concept of Java Dynamic Binding:

package com.dataflair.javapolymorphism;
class Dynamic {
  public void dynamicbind() {
    System.out.println("Original method dynamic bind of type Dynamic. ");
  }
}

public class DynamicBinding extends Dynamic {
  public void dynamicbind() {
    System.out.println("This is Dynamic Binding");
  }
  public static void main(String[] args) {
    DynamicBinding db = new DynamicBinding();
    db.dynamicbind();

  }

}

Output:

This is Dynamic Binding

Note that the compiler cannot determine the type of the method because it is in two places, class DynamicBinding, and class Dynamic. Only during runtime, the compiler binds the method name to the call. This is Dynamic Binding.

Covariant return types in Java

Java allows different return types of overridden methods. Simply put, if the return type of a parent class is of its own type then the same method in its child class can have a different return type.

However, the return type is non-primitive.

JVM allows the return type based overloading but java does not. This is because JVM uses the entire signature of the method for its resolution.

The signature contains the return type of the method and hence the Java compiler uses Covariant return types.

Java program to understand the concept of Covariant return types:

package com.dataflair.javapolymorphism;
class Parent {
  Parent covar() {
    return this;
  }

}
class Child extends Parent {
  Child covar() {
    return this;
  }
  void print() {
    System.out.println("This is the covariant return type.");
  }
}

public class CovarReturn {
  public static void main(String[] args) {
    new Child().covar().print();
  }

}

Output:

This is the covariant return type.

Final Keyword in Java

The final keyword has a lot of functions in Java. As the name suggests, it finalizes a variable, method, or class.

  • If you try to change the value of a final variable, it will log a compile error.
  • When you finalize a method, you cannot override it anymore.
  • If you finalize a class, then you cannot inherit it. However, final methods do support inheritance.
  • If a variable is static and final, then you cannot initialize this variable anywhere except the static block.

Note that constructors are never final because they are not inherited.

Program to understand the concept of Java final keyword:

package com.dataflair.javapolymoprhism;
public class FinalKeyword {
  final int WHEELS;
  FinalKeyword() {
    WHEELS = 4;
  }
  void print() {
    System.out.println(++WHEELS); //This statement would result in an error
    System.out.println(WHEELS);
  }
  public static void main(String[] args) {
    FinalKeyword f = new FinalKeyword();
    f.print();
  }
}

Output:

FinalKeyword.java:9: error: cannot assign a value to final variable WHEELS
System.out.println(++WHEELS);//This statement would result in an error

Now we will see what happens if we try to inherit a final class:

package com.dataflair.javapolymorphism;
final class FinalClass {
  int a;

}

public class FinalKeyword extends FinalClass {
  final int WHEELS;
  FinalKeyword() {
    WHEELS = 4;
  }
  void print() {
    //System.out.println(++WHEELS);//This statement would result in an error
    System.out.println(WHEELS);
  }
  public static void main(String[] args) {
    FinalKeyword f = new FinalKeyword();
    f.print();
  }
}

Output:

FinalKeyword.java:8: error: cannot inherit from final FinalClass
public class FinalKeyword extends FinalClass {

Now we will see what happens if we try to override a final method:

package com.dataflair.javapolymorphism;
class FinalClass {
  int a;
  public final void print() {
    System.out.println("This is a parent-class method. ");
  }

}

public class FinalKeyword extends FinalClass {
  final int WHEELS;
  FinalKeyword() {
    WHEELS = 4;
  }
  void print() {
    //System.out.println(++WHEELS);//This statement would result in an error
    System.out.println(WHEELS);
  }
  public static void main(String[] args) {
    FinalKeyword f = new FinalKeyword();
    f.print();
  }
}

Output:

FinalKeyword.java:18: error: print() in FinalKeyword cannot override print() in FinalClass
void print()
^
overridden method is final
1 error

Advantages of Polymorphism in Java

  • A single function can behave differently in different classes.
  • Eliminates the need for declaring different function names for the same implementation
  • Implementing inheritance is easier with polymorphism.

Disadvantages of Polymorphism in Java

  • It is difficult for some programmers to implement polymorphism.
  • Runtime polymorphism degrades machine performance as the compiler decides the return type of the method during execution.
  • The readability of the program decreases because the runtime implementation points to how much time the program is going to take to execute.

Characteristics of Java Polymorphism

Apart from the ones we talk about, there are a few characteristics that seldom meet the eye. They are:

a. Operator Overloading- Remember the first example we saw in this article about operator overloading?

You may notice that Java uses the plus(+)operator to concatenate strings and add integers. This is an example of an Operator overloading.

b. Polymorphic Parameters- There are ways by which we can have a variable of the same name but different types.

But these may result in a condition “variable hiding” which simply means that one of the variable’s value gets hidden as both of them have the same name.

A point to note is that local and global variables with the same name can be differentiated by this keyword.

c. Polymorphic Coercion-This is the work of the compiler which implicitly converts data types to prevent type errors.

For example when you declare a variable like this String s=2; the compiler converts the integer value to the string implicitly.

Summary

In this article, we came to know about a lot of new concepts in the field of programming.

Polymorphism is an important aspect of every Object-Oriented Language.

Hence, a strong concept of the same is essential to write efficient code which is easy to understand.

Did you like our efforts? If Yes, please give DataFlair 5 Stars on Google | Facebook

2 Responses

  1. Tiruvallam Pede says:

    I really liked the explanation and the examples given with them. Everything is nicely explained. Really nice article.

    • DataFlair Team says:

      We are glad that our readers are liking DataFlair articles. Do follow the side bar to learn Java from basics with Practicals.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.