Polymorphism in Java – Master the Concept in Just 7 Mins.
Get Job-ready: Java Course with 45+ Real-time Projects! - Learn Java
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.
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:
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 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:
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:
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.
Method overriding is a cornerstone of polymorphism in Java. It enables you to redefine the behavior of inherited methods in subclasses. This creates a more specialized implementation tailored to the subclass’s specific needs. By overriding methods, you can leverage the existing functionality of parent classes while introducing customized actions in child classes. This promotes code reusability, maintainability, and flexibility in object-oriented design.
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:
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:
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.
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:
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:
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:
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:
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:
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:
void print()
^
overridden method is final
1 error
Advantages of Polymorphism in Java
Polymorphism offers several advantages that make it a valuable concept for Java programmers. Here are some key benefits:
1. Code Reusability: By creating generic methods that can handle different object types, you can write code that is more reusable and adaptable. This reduces redundancy and promotes code maintainability.
2. Flexibility: Polymorphism allows your code to work seamlessly with various object types without requiring extensive modifications. This enhances the flexibility of your programs.
3. Dynamic Binding: Runtime polymorphism enables the compiler to determine the appropriate method implementation at runtime based on the actual object type. This dynamic approach leads to more efficient and adaptable code execution.
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 this article? If Yes, please give DataFlair 5 Stars on Google
I really liked the explanation and the examples given with them. Everything is nicely explained. Really nice article.
We are glad that our readers are liking DataFlair articles. Do follow the side bar to learn Java from basics with Practicals.
Hi 5th questions answer is wrong and the right answer is Webservices. Could you please confirm from your side as well.
Webservices is the right answer after explicitly casting the obj to Second to access the Display method, and it prints the value of a from the Second class, which is “Webservices”.
((Second) obj).Display();