DEV Community

Cover image for Java for beginners: Polymorphism in Java
Jeff Odhiambo
Jeff Odhiambo

Posted on

Java for beginners: Polymorphism in Java

Polymorphism is the ability of an object to take on many forms. In OOP, polymorphism is the capability of an action or method to do different things based on the object that it is acting upon.
This is the third basic principle of object oriented programming. Polymorphism in Java has two types: Compile time polymorphism (static binding) and Runtime polymorphism (dynamic binding).

Compile time (Static) polymorphism

A static polymorphism is one which method binds at compile time, also known as Compile time or static polymorphism. Static polymorphism is achieved through method(function) overloading or operator overloading. But Java doesn’t support the Operator Overloading.

Overloaded methods

When there are multiple functions (methods) with same name but different parameters (implementation) then these functions are said to be overloaded. Thus, functions can be overloaded by change in number of arguments or/and change in type of arguments.
These overloaded methods have same name signature but either a different number of parameters or different types in the parameter list. Overloaded methods:

  1. Appear in the same class or a subclass.
  2. Have the same name but.
  3. Have different parameter lists.
  4. Can have different return types.

At compile time, Java knows which method to invoke by checking the method signatures. So, this is called compile time polymorphism or static binding. The concept will be clear from the following example:

class DemoOverload{
    public int add(int x, int y){ //method 1
        return x+y;
    public int add(int x, int y, int z){ //method 2
        return x+y+z;
    public int add(double x, int y){ //method 3
        return (int)x+y;
    public int add(int x, double y){ //method 4
        return x+(int)y;
class Test{
    public static void main(String[] args){
        DemoOverload demo=new DemoOverload();
Enter fullscreen mode Exit fullscreen mode

Constructor Overloading:

  • Constructor overloading is a technique in Java in which a class can have any number of constructors that differ in parameter lists.
  • The compiler differentiates these constructors by taking into account the number of parameters in the list and their type.
class Room
    double length,breadth,height;
    Room(double l,double b,double h)
    Room(double len)
    double volume()
        return length*breadth*height;
class OverloadConstructors
    public static void main(String args[])
        Room a=new Room(20,30,40);
        Room b=new Room();
        Room c=new Room(10);
        double vol;
        System.out.println("Volume of room a is " + vol);
        System.out.println("Volume of room b is " + vol);
        System.out.println("Volume of room c is " + vol);
Enter fullscreen mode Exit fullscreen mode

Limitation: Poor utilization of memory resource (main memory).

Dynamic (Run Time) Polymorphism:

It is a process in which a function call to the overridden method is resolved at Runtime. This type of polymorphism is achieved by Method Overriding.
Run time polymorphism occurs when a sub class overrides a particular method of the super class.

Dynamic Binding (Late Binding)

When a method is invoked, the code to be executed is only determined at run-time. During the compilation, the compiler checks whether the method exists and performs type check on the arguments and return type, but does not know which piece of codes to execute at run-time. When a message is sent to an object to invoke a method, the object figures out which piece of codes to execute at run-time. This mechanism is called dynamic binding (or late-binding or run-time binding).

In polymorphism, Dynamic (or late) method binding is the ability of a program to resolve references to subclass methods at runtime.

Overridden Methods

Overridden methods are methods of a super class that are redefined(defined again) within a subclass.
In Java, you can create a method in a superclass (or parent class), then in a subclass ALSO define that

class Vehicle{
    public void move(){
        System.out.println("Vehicles can move!!");
class MotorBike extends Vehicle{
    public void move(){
        System.out.println("MotorBike can move and accelerate too!!");
class Test{
    public static void main(String[] args){
        Vehicle vh=new MotorBike();
        vh.move(); // prints MotorBike can move and accelerate too!!
        vh=new Vehicle();
        vh.move(); // prints Vehicles can move!!
Enter fullscreen mode Exit fullscreen mode

It should be noted that in the first call to move(), the reference type is Vehicle and the object being referenced is MotorBike. So, when a call to move() is made, Java waits until runtime to determine
which object is actually being pointed to by the reference. In this case, the object is of the class MotorBike. So, the move() method of MotorBike class will be called. In the second call to move(), the object is of the class Vehicle. So, the move() method of Vehicle will be called. As the method to call is determined at runtime, this is called dynamic binding or late binding.


  • applies ONLY to inherited methods is related to polymorphism
  • object type (NOT reference variable type) determines which overridden method will be used at runtime
  • overriding method MUST have the same argument list (if not, it might be a case of overloading)
  • overriding method MUST have the same return type; the exception is covariant return (used as of Java 5) which returns a type that is a subclass of what is returned by the overridden method
  • overriding method MUST NOT have more restrictive access modifier, but MAY have less restrictive one
  • overriding method MUST NOT throw new or broader checked exceptions, but MAY throw fewer or narrower checked exceptions or any unchecked exceptions
  • abstract methods MUST be overridden
  • final methods CANNOT be overridden
  • static methods CANNOT be overridden
  • constructors CANNOT be overridden ##Upcasting & Downcasting Upcasting a Subclass Instance to a Superclass Reference Substituting a subclass instance for its superclass is called "upcasting". This is because, in a UML class diagram, subclass is often drawn below its superclass. Upcasting is always safe because a subclass instance possesses all the properties of its superclass and can do whatever its superclass can do. The compiler checks for valid upcasting and issues error "incompatible types" otherwise. For example,
Circle c1 = new Cylinder(); // Compiler checks to ensure that R-value is a subclass of L-value
Circle c2 = new String(); // Compilation error: incompatible types
Enter fullscreen mode Exit fullscreen mode

Downcasting a Substituted Reference to Its Original Class
You can revert a substituted instance back to a subclass reference. This is called "downcasting". For

Cycle c1 = new Cylinder(5.0); // upcast is safe
Cylinder aCylinder = (Cylinder) c1; // downcast needs the casting operator
Enter fullscreen mode Exit fullscreen mode

Downcasting requires explicit type casting operator in the form of prefix operator (new-type).
Downcasting is not always safe, and throws a runtime ClassCastException if the instance to be downcasted does not belong to the correct subclass. A subclass object can be substituted for its superclass, but the reverse is not true.
Compiler may not be able to detect error in explicit cast, which will be detected only at runtime.
For example,

Circle c1 = new Circle(5);
Point p1 = new Point();
c1 = p1; // compilation error: incompatible types (Point is not subclass of Circle)
c1 = (Circle)p1; // runtime error: java.lang.ClassCastException: Point cannot be casted to Circle
Enter fullscreen mode Exit fullscreen mode

The instanceof Operator
Java provides a binary operator called instanceof which returns true if an object is an instance of a particular class. The syntax is as follows:

Circle c1 = new Circle();
System.out.println(c1 instanceof Circle); // true
if (c1 instanceof Cirlce){
Enter fullscreen mode Exit fullscreen mode

An instance of subclass is also an instance of its superclass. For example,

Circle c1 = new Circle(5);
Cylinder cy1 = new Cylinder(5, 2);
System.out.println(c1 instanceof Circle); //true
System.out.println(c1 instanceof Cylinder); //false
System.out.println(cy1 instanceof Cylinder); //true
System.out.println(cy1 instanceof Circle);  //true

Circle c2 = new Cylinder(5, 2);
System.out.println(c2 instanceof Circle); //true
System.out.println(c2 instanceof Cylinder); //true
Enter fullscreen mode Exit fullscreen mode


  • The method binding happens at the compile time i.e which methods can be invoked on a given reference type is decided at the compile time.
  • The selection of the method’s implementation to execute happens at the run time i.e which implementation of the method to be executed i.e the super class version or one of the subclass’s version is decided at the run time and this is what leads to the runtime polymorphism.
  • An object in Java that passes more than one IS-A tests is polymorphic in nature
  • Static polymorphism in Java is achieved by method overloading
  • Dynamic polymorphism in Java is achieved by method overriding

Our last article on Java for beginners will be on Java Packages. If you missed the previous articles on Java for beginners check on them through the links below

  1. Java for Beginners: Introduction to Java
  2. Java for beginners: Installation of Java
  3. Java for beginners: Fundamentals of Java
  4. Java Object Oriented Programming Thanks for taking your time to read this article. see you in the next article.

Top comments (0)