Home Java javaTutorial Detailed introduction to static binding and dynamic binding in Java

Detailed introduction to static binding and dynamic binding in Java

Dec 26, 2016 pm 04:17 PM

The execution of a Java program requires two steps: compilation and execution (interpretation). At the same time, Java is an object-oriented programming language. When the subclass and the parent class have the same method, and the subclass overrides the method of the parent class, when the program calls the method at runtime, should it call the method of the parent class or the overridden method of the subclass? This should be the question when we first learn Java. problems encountered. Here first we will determine which method to call or the operation of variables is called binding.

There are two binding methods in Java, one is static binding, also called early binding. The other is dynamic binding, also known as late binding.

Difference comparison

1. Static binding occurs at compile time, dynamic binding occurs at runtime
2. Use variables or methods modified with private or static or final, use static Binding. Virtual methods (methods that can be overridden by subclasses) will be dynamically bound according to the runtime object.
3. Static binding is completed using class information, while dynamic binding needs to be completed using object information.
4. The overloaded method is completed using static binding, while the overriding method is completed using dynamic binding.

Example of overloaded method

Here is an example of overloaded method.

public class TestMain {
  public static void main(String[] args) {
      String str = new String();
      Caller caller = new Caller();
      caller.call(str);
  }
  static class Caller {
      public void call(Object obj) {
          System.out.println("an Object instance in Caller");
      }
      
      public void call(String str) {
          System.out.println("a String instance in in Caller");
      }
  }
}
Copy after login

The execution result is

22:19 $ java TestMain
a String instance in in Caller
Copy after login

In the above code, there are two overloaded implementations of the call method. One receives an object of type Object as a parameter, and the other receives String. Object of type as parameter. str is a String object, and all call methods that receive String type parameters will be called. The binding here is static binding based on the parameter type at compile time.

Verification

Just looking at the appearance cannot prove that static binding is performed. You can verify it by using javap to compile it.

22:19 $ javap -c TestMain
Compiled from "TestMain.java"
public class TestMain {
  public TestMain();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/String
       3: dup
       4: invokespecial #3                  // Method java/lang/String."<init>":()V
       7: astore_1
       8: new           #4                  // class TestMain$Caller
      11: dup
      12: invokespecial #5                  // Method TestMain$Caller."<init>":()V
      15: astore_2
      16: aload_2
      17: aload_1
      18: invokevirtual #6                  // Method TestMain$Caller.call:(Ljava/lang/String;)V
      21: return
}
Copy after login

saw this line 18: invokevirtual #6 // Method TestMain$Caller.call:(Ljava/lang/String;)V is indeed statically bound, and it is confirmed that the call receives the String object as Parameter caller method.

Example of overriding method

public class TestMain {
  public static void main(String[] args) {
      String str = new String();
      Caller caller = new SubCaller();
      caller.call(str);
  }
  
  static class Caller {
      public void call(String str) {
          System.out.println("a String instance in Caller");
      }
  }
  
  static class SubCaller extends Caller {
      @Override
      public void call(String str) {
          System.out.println("a String instance in SubCaller");
      }
  }
}
Copy after login

The execution result is

22:27 $ java TestMain
a String instance in SubCaller
Copy after login

The above code has an implementation of the call method in Caller. SubCaller inherits Caller and rewrites it. The implementation of the call method. We declared a variable callerSub of type Caller, but this variable points to a SubCaller object. According to the results, it can be seen that it calls the call method implementation of SubCaller instead of the call method of Caller. The reason for this result is that dynamic binding occurs at runtime, and during the binding process it is necessary to determine which version of the call method implementation to call.

Verification

Dynamic binding cannot be directly verified using javap. If it is proved that static binding is not performed, it means that dynamic binding is performed.

22:27 $ javap -c TestMain
Compiled from "TestMain.java"
public class TestMain {
  public TestMain();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/String
       3: dup
       4: invokespecial #3                  // Method java/lang/String."<init>":()V
       7: astore_1
       8: new           #4                  // class TestMain$SubCaller
      11: dup
      12: invokespecial #5                  // Method TestMain$SubCaller."<init>":()V
      15: astore_2
      16: aload_2
      17: aload_1
      18: invokevirtual #6                  // Method TestMain$Caller.call:(Ljava/lang/String;)V
      21: return
}
Copy after login

As the above result, 18: invokevirtual #6 // Method TestMain$Caller.call:(Ljava/lang/String;)V Here is TestMain$Caller.call instead of TestMain$SubCaller.call, Because the compile time cannot determine whether to call the implementation of the subclass or the parent class, it can only be left to the dynamic binding at runtime.

When overloading meets overriding

The following example is a bit abnormal. There are two overloads of the call method in the Caller class. What is more complicated is that SubCaller integrates Caller and rewrites this Two methods. In fact, this situation is a compound situation of the above two situations.

The following code will first be statically bound to determine the call method whose parameter is a String object, and then dynamically bound at runtime to determine whether to execute the call implementation of the subclass or the parent class.

public class TestMain {
  public static void main(String[] args) {
      String str = new String();
      Caller callerSub = new SubCaller();
      callerSub.call(str);
  }
  
  static class Caller {
      public void call(Object obj) {
          System.out.println("an Object instance in Caller");
      }
      
      public void call(String str) {
          System.out.println("a String instance in in Caller");
      }
  }
  
  static class SubCaller extends Caller {
      @Override
      public void call(Object obj) {
          System.out.println("an Object instance in SubCaller");
      }
      
      @Override
      public void call(String str) {
          System.out.println("a String instance in in SubCaller");
      }
  }
}
Copy after login

The execution result is

22:30 $ java TestMain
a String instance in in SubCaller
Copy after login

Verification

Since it has been introduced above, I will only post the decompilation result here

22:30 $ javap -c TestMain
Compiled from "TestMain.java"
public class TestMain {
  public TestMain();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return
  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class java/lang/String
       3: dup
       4: invokespecial #3                  // Method java/lang/String."<init>":()V
       7: astore_1
       8: new           #4                  // class TestMain$SubCaller
      11: dup
      12: invokespecial #5                  // Method TestMain$SubCaller."<init>":()V
      15: astore_2
      16: aload_2
      17: aload_1
      18: invokevirtual #6                  // Method TestMain$Caller.call:(Ljava/lang/String;)V
      21: return
}
Copy after login

Curious questions

Isn’t it possible to have dynamic binding?

In fact, theoretically, the binding of certain methods can also be achieved by static binding. For example:

public static void main(String[] args) {
      String str = new String();
      final Caller callerSub = new SubCaller();
      callerSub.call(str);
}
Copy after login

For example, here callerSub holds the object of subCaller and the callerSub variable is final, and the call method is executed immediately. In theory, the compiler can know that the call method of SubCaller should be called by sufficient analysis of the code.

But why is there no static binding?
Assume that our Caller inherits from the BaseCaller class of a certain framework, which implements the call method, and BaseCaller inherits from SuperCaller. The call method is also implemented in SuperCaller.

Suppose BaseCaller and SuperCaller in a certain framework 1.0

static class SuperCaller {
  public void call(Object obj) {
      System.out.println("an Object instance in SuperCaller");
  }
}
  
static class BaseCaller extends SuperCaller {
  public void call(Object obj) {
      System.out.println("an Object instance in BaseCaller");
  }
}
Copy after login

and we use framework 1.0 to implement this. Caller inherits from BaseCaller and calls the super.call method.

public class TestMain {
  public static void main(String[] args) {
      Object obj = new Object();
      SuperCaller callerSub = new SubCaller();
      callerSub.call(obj);
  }
  
  static class Caller extends BaseCaller{
      public void call(Object obj) {
          System.out.println("an Object instance in Caller");
          super.call(obj);
      }
      
      public void call(String str) {
          System.out.println("a String instance in in Caller");
      }
  }
  
  static class SubCaller extends Caller {
      @Override
      public void call(Object obj) {
          System.out.println("an Object instance in SubCaller");
      }
      
      @Override
      public void call(String str) {
          System.out.println("a String instance in in SubCaller");
      }
  }
}
Copy after login

Then we compiled the class file based on version 1.0 of this framework. Assuming that static binding can determine that the super.call of the above Caller is implemented as BaseCaller.call.

Then we again assume that BaseCaller does not rewrite the call method of SuperCaller in version 1.1 of this framework. Then the above assumption that the call implementation that can be statically bound will cause problems in version 1.1, because in version 1.1 super. The call should be implemented using the call method of SuperCall, rather than the call method of BaseCaller determined by static binding.

So, some things that can actually be bound statically are simply bound dynamically in consideration of security and consistency.

Optimization inspiration obtained?

Because dynamic binding needs to determine which version of the method implementation or variable to execute at runtime, it is more time-consuming than static binding.

So without affecting the overall design, we can consider modifying methods or variables with private, static or final.

For more detailed introduction to static binding and dynamic binding in Java, please pay attention to the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

Java Tutorial
1663
14
PHP Tutorial
1263
29
C# Tutorial
1237
24
Is the company's security software causing the application to fail to run? How to troubleshoot and solve it? Is the company's security software causing the application to fail to run? How to troubleshoot and solve it? Apr 19, 2025 pm 04:51 PM

Troubleshooting and solutions to the company's security software that causes some applications to not function properly. Many companies will deploy security software in order to ensure internal network security. ...

How do I convert names to numbers to implement sorting and maintain consistency in groups? How do I convert names to numbers to implement sorting and maintain consistency in groups? Apr 19, 2025 pm 11:30 PM

Solutions to convert names to numbers to implement sorting In many application scenarios, users may need to sort in groups, especially in one...

How to simplify field mapping issues in system docking using MapStruct? How to simplify field mapping issues in system docking using MapStruct? Apr 19, 2025 pm 06:21 PM

Field mapping processing in system docking often encounters a difficult problem when performing system docking: how to effectively map the interface fields of system A...

How does IntelliJ IDEA identify the port number of a Spring Boot project without outputting a log? How does IntelliJ IDEA identify the port number of a Spring Boot project without outputting a log? Apr 19, 2025 pm 11:45 PM

Start Spring using IntelliJIDEAUltimate version...

How to elegantly obtain entity class variable names to build database query conditions? How to elegantly obtain entity class variable names to build database query conditions? Apr 19, 2025 pm 11:42 PM

When using MyBatis-Plus or other ORM frameworks for database operations, it is often necessary to construct query conditions based on the attribute name of the entity class. If you manually every time...

How to safely convert Java objects to arrays? How to safely convert Java objects to arrays? Apr 19, 2025 pm 11:33 PM

Conversion of Java Objects and Arrays: In-depth discussion of the risks and correct methods of cast type conversion Many Java beginners will encounter the conversion of an object into an array...

How to use the Redis cache solution to efficiently realize the requirements of product ranking list? How to use the Redis cache solution to efficiently realize the requirements of product ranking list? Apr 19, 2025 pm 11:36 PM

How does the Redis caching solution realize the requirements of product ranking list? During the development process, we often need to deal with the requirements of rankings, such as displaying a...

E-commerce platform SKU and SPU database design: How to take into account both user-defined attributes and attributeless products? E-commerce platform SKU and SPU database design: How to take into account both user-defined attributes and attributeless products? Apr 19, 2025 pm 11:27 PM

Detailed explanation of the design of SKU and SPU tables on e-commerce platforms This article will discuss the database design issues of SKU and SPU in e-commerce platforms, especially how to deal with user-defined sales...

See all articles