Dynamic Method Dispatch in Java

In Java, dynamic method dispatch is a technique in which an object refers to superclass but at runtime, the object is constructed for subclass.

In other words, it is a technique in which a superclass reference variable refers to a subclass object. It is also known as upcasting in Java.

Java uses this mechanism to resolve a call to an overridden method at runtime rather than compile time. The overridden method is called through the reference variable of a superclass.

The determination of the method to be called is based on the object being referred to by the reference variable. In the dynamic dispatch method technique, we can declare a super class reference variable equal to sub class object like this:

SuperClass sc = new ChildClass(); // sc is super class reference variable which is pointing to child class object.

Dynamic dispatch method is important because it is a process through which Java implements runtime polymorphism. Let’s understand the dynamic method dispatch more clearly by different example programs.

Java Dynamic Method Dispatch Example Program


Let’s take an example program in which we will illustrate dynamic method dispatch using hierarchical inheritance in Java.

Example 1:

package dynamicMethodDispatchProgram; 
public class A 
{ 
   void m1() 
   { 
      System.out.println("m1-A"); 
   } 
} 
public class B extends A 
{ 
// Overriding m1() method of superclass in the subclass. 
   void m1() 
   { 
      System.out.println("m1-B"); 
   } 
} 
public class C extends B 
{ 
// Overriding m1() method of superclass into the subclass. 
   void m1() 
   { 
      System.out.println("m1-C"); 
   } 
} 
public class Test { 
public static void main(String[] args) 
{ 
 // Creating an object of class A. 
 // Here, "a" is a reference variable of type A, which is pointing to the object of class A. 
    A a = new A(); // Object of type A.
     a.m1(); 

 // Creating an object of class B.
 // Here, "b" is a reference variable of type B which is pointing to the object of class B.
    B b = new B(); 
     b.m1(); 

 // Creating an object of class C.
 // Here, "c" is a reference variable of type C, which is pointing to the object of class C. 
    C c = new C(); // Object of type C. 
     c.m1(); 
  
     A a2; // A reference variable of type A. 
     a2 = b; // Reference a1 refers to Class B's object. 
     a2.m1(); 
     
     a2 = c; // Reference a1 refers to Class C's object. 
     a2.m1(); 
     
     B b2 = c; // Reference variable b2 of type B refers to class C's object. 
     b2.m1(); 
  } 
}
Output: 
       m1-A 
       m1-B 
       m1-C 
       m1-B 
       m1-C 
       m1-C

Explanation:

In the preceding program, we have created one super class called A and it’s two sub classes B and C. These sub classes override m1( ) method.


1. Inside the main() method in class Test, initially, objects of type A, B, and C are declared.

a) When a.m1(); will be executed, it will call method m1() of class A because reference variable “a” is pointing towards object of class A.

b) b.m1(); will call m1() of class B because reference variable “b” refers to object of class B.

c) c.m1(); will invoke m1() of class C because reference variable “c” is pointing towards object of class C.

2. When A a2 is declared, initially it will point to null.

a) a2.m1(); will call m1() of class B because “a2” is reference variable of type A but it is pointing towards class B’s object.

b) a2.m1(); will call m1() of class C. This is because “a2” is referring to class C’s object.

3. b2.m1(); will call m1() of class C because “b2” of type B is pointing to class C’s object.

This is a simple example program of dynamic method dispatch in Java. If you have any problem understanding the above concept, then first, read the below topic. In this topic, we have explained the concept of method overriding with real-time example and important programs, which you can understand easily.


Read: Method overriding in Java with Example Program


Let’s take another example program based on the concept of dynamic method dispatch in Java.

Example 2:

package dynamicMethodDispatchProgram; 
public class X 
{ 
   X() 
   { 
      System.out.println("Parent class constructor"); 
      m1(); 
   } 
   void m1()
   { 
     System.out.println("Parent method"); 
   } 
} 
public class Y extends X 
{ 
   Y() 
   { 
      System.out.println("Child class constructor"); 
   } 
   void m1() 
   { 
      System.out.println("Child class method"); 
   } 
} 
public class Demo extends Y { 
public static void main(String[] args) 
{ 
    Y y = new Y(); 
     y.m1(); 
    
    X x = new Y(); 
     x.m1(); 
    
    Y y2 = new Demo(); 
     y2.m1(); 
  } 
}

Output: 
       Parent class constructor 
       Child class method 
       Child class constructor 
       Child class method
 
       Parent class constructor 
       Child class method 
       Child class constructor 
       Child class method 
       Parent class constructor 
       Child class method 
       Child class constructor 
       Child class method

Explanation of flow of execution of the above program:

Flow of execution of dynamic method dispatch program in Java.

1. Inside the main() method of Demo class, when the statement Y y = new Y(); will be executed, the control of execution will be immediately transferred class Y’s constructor.

From there, superclass constructor will be called and the control of execution will be transferred to class X’s constructor. The first output will be printed “Parent class constructor”.

2. From the superclass constructor, m1() method of class Y will be called because the reference variable “y” is pointing to the object of class Y. The second output will be “Child class method”.

3. After the execution of m1() method, the control of execution will be again immediately transferred to class Y’s constructor. The third output will be “Child class constructor”.

4. The line y.m1(); will call m1() of class Y because “y” refers to object of class Y. The fourth output is “Child class method”. Similarly, for the other two statements.

Example 3:

package dynamicMethodDispatchProgram; 
public class XX 
{ 
// Declaration of instance block. 
   { 
     m1(); 
   } 
// Constructor declaration.
   XX() 
   { 
      System.out.println("Parent class constructor"); 
      m1(); 
   }
// Method declaration. 
   void m1() 
   { 
     System.out.println("Parent class method"); 
   } 
} 
public class YY extends XX 
{ 
// Constructor declaration.
   YY() 
   { 
      System.out.println("Child class constructor"); 
   } 
// Overriding the method of superclass in subclass.
   void m1()
   { 
      System.out.println("Child class method"); 
   } 
} 
public class Myclass { 
public static void main(String[] args) 
{ 
    XX x = new YY(); 
    x.m1(); 
  } 
}
Output: 
       Child class method 
       Parent class constructor 
       Child class method 
       Child class constructor 
       Child class method

Explanation:

1. During the execution of above program, when the statement XX x = new YY(); will be executed, the constructor of class YY will be called and the control of execution will be immediately transferred to class YY’s constructor. From there, super class constructor XX() will be called.

But we know that before the execution of constructor, instance block is executed. Inside the instance block, m1() of class YY will be called because the reference variable “x” is pointing to the child class object. Therefore, the first output is “Child class method”.

2. After the complete execution of instance block, superclass constructor is executed. Therefore, the second output is “Parent class constructor”.

3. Inside the superclass constructor, m1(); will call m1() method of class YY. Therefore, the third output is “Child class method”.

4. After the complete execution of superclass constructor, the control of execution will be transferred back to the child class constructor. It will print “Child class constructor”. This is the fourth output.

5. The line x.m1(); will call m1() of class YY because the reference variable “y” is pointing to the object of class YY. Therefore, the fifth output is “Child class method”.

Let’s take an example program in which we will declare two methods m1() and m2() in the parent class but in the child class, we will override only m1() method. We will also declare a new method m3() in the child class. Let’s see the following program code.

Example 4:

package dynamicMethodDispatchProgram; 
public class ParentClass 
{ 
   void m1()
   { 
      System.out.println("ParentClass m1"); 
   } 
   void m2() 
   { 
      System.out.println("ParentClass m2"); 
   } 
} 
public class ChildClass extends ParentClass 
{ 
   void m1() 
   { 
      System.out.println("ChildClass m1"); 
   } 
  void m3() 
  { 
     System.out.println("ChildClass m3"); 
  } 
} 
public class Mytest { 
public static void main(String[] args) 
{ 
    ParentClass p = new ChildClass(); 
    p.m1(); 
    p.m2(); 
 
 // p.m3(); // The method m3() is undefined for the type ParentClass. 
 } 
}
Output: 
       ChildClass m1 
       ParentClass m2

Key Points to Remember:

Dynamic dispatch in Java is a powerful concept in object-oriented programming language that allows a program to resolve method calls at runtime rather than compile time. In the dynamic method dispatch mechanism, there are two key points that you should keep in mind.

1. The object can call the overriding method of child class as well as all non-overridden methods of the superclass. For example, in the preceding program, using reference variable “p”, we are called m1() and m2() methods.

2. The object cannot call methods that are newly added in the child class. For example, we have declared a new method m3() in the child class, but it cannot be called because the method is undefined for type ParentClass.