I'm Utkarsh, a student pursuing the field of Computer Science Engineering alongside a corporate career in Full Stack Development, Creative Content Writing, and as a Marketing Associate, with more than 5 years of experience.
For enquiries call:
+1-469-442-0620
HomeBlogProgrammingPolymorphism in Java
Java is simply an object-oriented language, meaning it organizes code into various reusable components called objects (e.g. think of these as real-life objects). The language comes with a very rich standard library that provides the developer with a vast array of various pre-built classes and optimized methods, enabling them to build some robust and efficient applications quickly and easily. In this article, we will talk about Polymorphism (an OOP – “Object Oriented Programming” concept) in Java.
Java comes with a very strict syntax and strong type-checking which ensure the code integrity and also reduces the likelihood of any errors. Its extensive toolset includes the Java Development Kit (popularly called as JDK), and various IDEs (Integrated Development Environments). Like Eclipse and IntelliJ IDEA, IDEs empower today’s developers with many powerful debugging tools, profiling, and also testing capabilities.
Let us begin with understanding polymorphism in Java. Polymorphism is a prime fundamental concept prevalent in object-oriented programming and is one of the key features of the widely used Java language. It allows objects of different classes to be taken as types of a common superclass or interface. Java Programming training will help you become an ace programmer with the most in-demand programming courses.
In the Java programming language, polymorphism is easily achieved with the implementation of method overriding and method overloading:
Polymorphism Promotes:
It allows for much more generic programming and also simplifies the process of code maintenance, as the changes made to the superclass or interface can also propagate to all implementing classes. Additionally, it facilitates the creation of frameworks and libraries that can work with different types of objects without requiring specific knowledge of their concrete implementations.
There are a plethora of reasons to use polymorphism in Java. Some of them are mentioned below:
In Java, polymorphism can be roughly categorized into two prime types:
Compile-time polymorphism in Java is achieved with the implementation of method overloading and operator overloading. What does method overloading and operator overloading do? Method overloading and operator overloading grants capabilities for multiple methods in a class and operators to have the same name but with different parameter list (different parameter types, numbers or sequence).
The compiler used for the code’s compilation then determines the appropriate method to be invoked based on the number, types, and order of the arguments passed during the method call. The decision is made at compile time. This type of polymorphism program in Java is resolved during the compilation process and thus the name "compile-time polymorphism”.
Compile-time Polymorphism in java Example:
public class PolymorphismExample { public static void main(String[] args) { int sum1 = add(5, 3); int sum2 = add(5, 3, 2); System.out.println("Sum 1: " + sum1); // Output: Sum 1: 8 System.out.println("Sum 2: " + sum2); // Output: Sum 2: 10 } public static int add(int a, int b) { return a + b; } public static int add(int a, int b, int c) { return a + b + c; } }
In this example, we have a class Polymorphism Example with two methods named add. These methods are overloaded, which means they have the same name but different parameter lists.
The first add method takes two integer parameters a and b and returns their sum. The second add method takes three integer parameters a, b, and c and returns their sum.
In the main method, we invoke the add method twice with different sets of arguments. The Java compiler determines which add method to call based on the number and types of arguments provided.
During the compile-time, the compiler matches the method calls with the appropriate method signatures. In this case, it selects the add method with two parameters for the first method call, and the add method with three parameters for the second method call.
The output will be "Sum 1: 8" and "Sum 2: 10", demonstrating how compile-time polymorphism resolves the method calls based on the static types of the arguments provided at compile-time.
Runtime (or dynamic) polymorphism is achieved with the application of method overriding. The decision of which method to invoke is determined at runtime based on the actual data type of the object.
Polymorphism in Java example programs for runtime polymorphism:
public class Animal { public void sound() { System.out.println("Animal makes a sound"); } } public class Dog extends Animal { @Override public void sound() { System.out.println("Dog barks"); } } public class Cat extends Animal { @Override public void sound() { System.out.println("Cat meows"); } }
The given code defines a hierarchy of classes: Animal, Dog, and Cat.
The Animal class has a method called sound(), which prints "Animal makes a sound" when called. The Dog and Cat classes are subclasses of Animal and override the sound() method with their own implementations.
In the Dog class, the sound() method is overridden to print "Dog barks" when called. Similarly, in the Cat class, the sound() method is overridden to print "Cat meows" when called.
When the code is executed using a compiler, if we create an instance of the class Animal and call its sound() method, it will print "Animal makes a sound". However, if we alternately create some instances of Dog or Cat and call their sound() methods, they will print "Dog barks" and "Cat meows", respectively.
The output of the code depends on which class's sound() method is called, resulting in the respective animal sound being printed.
At runtime, the appropriate `sound()` method is called based on the actual type of the object:
Animal animal1 = new Dog(); animal1.sound(); // Output: "Dog barks" Animal animal2 = new Cat(); animal2.sound(); // Output: "Cat meows"
Runtime polymorphism allows for dynamic binding, where the method implementation is resolved based on the actual type of the object at runtime, rather than the reference type. Get ahead of the race and learn more with Python Programming course online.
Let us explore the prime characteristics of polymorphism:
Coercion, which is also known as implicit type conversion, is an important characteristic of polymorphism, where the language automatically converts one type of data into usable another type when required. In Java, this is commonly seen in use in numeric promotions, where smaller data types are automatically promoted to larger ones to perform arithmetic operations without explicit casting.
public class NumericPromotionExample { public static void main(String[] args) { int x = 5; double y = 2.5; double result = x + y; // int 'x' is promoted to double for addition System.out.println("Result: " + result); // Output: Result: 7.5 } }
In this example, we have made use of an int variable x with a value of 5 and a double variable y with a value of 2.5. When we perform the addition x + y, the int value x is automatically promoted to the usage of a double to match the data type of y. This promotion allows the addition to be performed without any explicit casting.
The resulting value is stored in the double variable result, which holds the value 7.5. Finally, the value of result is printed, displaying "Result: 7.5" as the output.
This example clearly demonstrates how using Java automatically promotes for usage of smaller data types, such as int, to larger data types, such as double, when performing arithmetic operations.
Java, however, has no operator overloading to date. But, internal operator overloading refers to the ability of built-in operators to act differently based on the operands' types. To take as an example, the + operator can perform addition for numeric operands and also string concatenation for string operands.
public class OperatorOverloadingExample { public static void main(String[] args) { int a = 5; int b = 3; String str1 = "Hello"; String str2 = " world!"; int sum = a + b; // Addition of numeric operands String concat = str1 + str2; // String concatenation System.out.println("Sum: " + sum); // Output: Sum: 8 System.out.println("Concatenation: " + concat); // Output: Concatenation: Hello world! } }
In this example, we have two int variables, a and b, holding the values 5 and 3, respectively. When we use the + operator with these numeric operands (a + b), the operator performs addition, resulting in the sum of 8.
We also have two String variables, str1 and str2, containing the strings "Hello" and " world!" respectively. When we use the + operator with these string operands (str1 + str2), the operator behaves differently based on the types of the operands. In this case, it performs string concatenation, combining the two strings to create a new string "Hello world!".
The results of both operations are then printed using System.out.println(), displaying "Sum: 8" and "Concatenation: Hello world!" as the output.
This example illustrates how the + operator in Java exhibits internal operator overloading by performing addition for numeric operands and string concatenation for string operands.
Polymorphic variables or also known as parameters refer to the ability to use a variable or any parameter of a superclass or interface type to refer to objects of different subclasses that will inherit from that superclass or also implement that interface. This allows for a much more flexible environment and code reuse, as a single variable or parameter can hold different object types, and the appropriate methods will be invoked based on the actual object at runtime.
public class PolymorphismExample { public static void main(String[] args) { Animal animal1 = new Dog(); Animal animal2 = new Cat(); animal1.sound(); // Output: Dog barks animal2.sound(); // Output: Cat meows } } class Animal { public void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override public void sound() { System.out.println("Dog barks"); } } class Cat extends Animal { @Override public void sound() { System.out.println("Cat meows"); } }
In this example, we have a class hierarchy consisting of the Animal class and its two subclasses Dog and Cat. The Animal class has a sound() method that prints "Animal makes a sound".
In the main() method, we declare two variables of type Animal, animal1 and animal2. However, we initialize animal1 with a Dog object and animal2 with a Cat object. This is possible because of polymorphism, where a superclass variable can refer to objects of its subclasses.
When we invoke the sound() method on animal1 and animal2, the appropriate sound() method of the actual objects (i.e., Dog and Cat) is called based on the runtime type of the objects. This is known as dynamic method dispatch, where the correct implementation of the method is determined at runtime.
As a result, the output will be "Dog barks" for animal1.sound() and "Cat meows" for animal2.sound(). This demonstrates how polymorphic variables allow for flexibility and code reuse by enabling a single variable to hold different object types and invoke the appropriate methods based on the actual object at runtime.
Subtype polymorphism, which is also known as Java inheritance polymorphism, is another prime characteristic. It has the capability for the objects of a subclass to be treated as objects of their superclass. This grants the ability to code to work with objects at a higher level of ease, promoting code reuse, modularity, and also flexibility to a greater degree. Method overriding is a key mechanism of subtype polymorphism, allowing subclasses to provide their own implementation of methods defined in the superclass.
These characteristics properties collectively contribute to the vast power and the versatility of polymorphism in Java, enabling for a much more flexible and modular code design and enhancing the code's ability to handle diverse object types.
public class PolymorphismExample { public static void main(String[] args) { Animal animal = new Dog(); // Subclass object treated as a superclass object animal.sound(); // Output: Dog barks } } class Animal { public void sound() { System.out.println("Animal makes a sound"); } } class Dog extends Animal { @Override public void sound() { System.out.println("Dog barks"); } }
In this example, we have a superclass Animal and its subclass Dog. The Animal class has a sound() method that prints "Animal makes a sound". The Dog class overrides the sound() method to provide its own implementation, which prints "Dog barks".
In the main() method, we create an object of the Dog class and assign it to a variable of the superclass type Animal. This is possible because of subtype polymorphism, where an object of a subclass can be treated as an object of its superclass.
When we invoke the sound() method on the animal object, it dynamically dispatches to the overridden method in the Dog class. This means that even though the reference type is Animal, the actual implementation called is from the Dog class.
As a result, the output will be "Dog barks". This demonstrates the power of subtype polymorphism, where objects of a subclass can be treated as objects of their superclass, promoting code reuse, modularity, and flexibility. Method overriding, as a key mechanism of subtype polymorphism, allows subclasses to provide their own implementation of methods defined in the superclass.
Advantages of Polymorphism in Java:
Here are a few real-life examples that involve polymorphism and polymorphism in Java is implemented through the following examples:
The easiest polymorphism in Java with real time example is the shape hierarchy program. Consider a software application that deals with various different shapes like circles, rectangles, and triangles. These shapes can be represented using a common superclass or an interface called "Shape." Each shape can have its own implementations in its methods like calculateArea() and draw(). By treating all shapes as instances of the "Shape" superclass or interface, you can perform operations like calculating the total area of a collection of shapes or displaying them on a screen, regardless of their specific type.
In media players, polymorphism can be observed when playing different types of media files such as audio and video. The media player can have a common "MediaPlayer" interface or superclass with methods like play(), pause(), and stop(). Each specific media type, such as MP3 or MP4, can have its own implementation of these methods. In this way, the media player can handle different file formats seamlessly, as long as they adhere to the common interface or superclass.
In a banking system, polymorphism can be utilized when handling various types of accounts like savings accounts, checking accounts, and investment accounts. These different account types can inherit from a common "Account" superclass or implement a common interface. The banking system can treat all accounts uniformly, allowing operations such as deposits, withdrawals, and interest calculations to be performed on any account object, regardless of its specific type.
In an office environment involving an employee management system, polymorphism can be applied when dealing with multiple different types of employees to keep track, such as full-time employees, part-time employees, and contractors. These employee types can be modeled using a common superclass or interface called "Employee." The system can treat all employees appropriately, allowing common operations like calculating salaries, managing leave requests, and accessing employee details to be performed on any employee object.
In the field of biology, polymorphism can be observed in animal classification. Each animal class or subclass can have its own unique characteristics and behaviors. By utilizing polymorphism, scientific studies and research can be conducted using common methods or interfaces that can be implemented by various animal types, regardless of their specific class or subclass.
These examples demonstrate how polymorphism in Java real-time examples allows for the flexibility, modularity, and code reusability in real-life applications across various domains.
Thus, it can be said that polymorphism is a very powerful and essential concept in Java and object-oriented programming for the modern-day developer environment and also in many workplace environments. It enables many useful features such as code reusability, flexibility, and modularity by allowing multiple objects of different classes to be treated uniformly through common interfaces or also super classes.
While the concept of polymorphism may introduce a slight performance overhead in some systems and also require thoughtful design considerations, the advantages that it brings outweigh the disadvantages in most cases. Real-life examples like shape hierarchies, media playback, banking systems, and employee management demonstrate the practical applications and benefits of polymorphism in various domains. Go for Java full course and learn from leading Java experts with industry experience.
The benefit of polymorphism in Java is that it immensely promotes the credibility of code reusability, thereby allowing objects of different classes to be treated uniformly through common interfaces or superclasses. This leads to more modular and maintainable code, as common behaviors can be defined once and shared across multiple subclasses.
One of the prime of polymorphism in Java can be defined as the shape hierarchy example, where different shapes like circles, rectangles, and triangles can be represented using a common superclass or interface called "Shape." This allows for many operations like calculating the total area of a collection of shapes or also displaying them on a screen, regardless of their specific type.
No , this is a concept, and overloading is a feature provided in Java. static polymorphism in Java solely refers to the compile-time polymorphism achieved through method overloading, where multiple different methods in a class have the same name but different parameter lists.
Name | Date | Fee | Know more |
---|