The execution of a Java program is compiled and executed (interpreted) both steps, while Java is an object-oriented programming language. When the subclass and the parent class have the same method, the subclass overrides the method of the parent class, the program calls the method at run time whether it calls the parent class's method or the subclass's override method, which should be the problem we encountered in the beginner java. Here we will first determine which method implementation or variable is called binding.
There are two ways of binding in Java, one for static binding and another for early binding. The other is dynamic binding, also known as late binding.
Difference contrast
1. Static binding occurs at compile time, and dynamic binding occurs at run time
2. Use static bindings with variables or methods that are either private or static or final decorated. Virtual methods, which can be overridden by a quilt class, are dynamically bound based on objects at run time.
3. Static bindings use class information to complete, while dynamic binding requires the use of object information.
4. Overloaded (overload) methods are completed using static bindings, while overridden (Override) methods are completed using dynamic binding.
Examples of overloaded methods
This shows an example of an overloaded method.
Copy Code code as follows:
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 Caller");
}
}
}
The results of the execution are
Copy Code code as follows:
22:19 $ java Testmain
A String instance in Caller
In the above code, the call method has two overloaded implementations, one to receive an object of type objects as a parameter, and the other to receive a string object as a parameter. STR is a string object, and all call methods that receive the string type parameters are invoked. The binding here is a static binding based on the parameter type at compile time.
Verify
The appearance of light can not prove that the static binding, the use of JAVAP to compile it can be validated.
Copy Code code as follows:
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
}
See this line 18:invokevirtual #6//Method Testmain$caller.call: (ljava/lang/string;) v Indeed, a static binding has occurred. Determines the caller method that invokes the receive string object as a parameter.
Examples of overriding methods
Copy Code code as follows:
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
&nb sp; public void call (String str) {
SYSTEM.OUT.PRINTLN ("a String instance in Subcaller");
}
}
}
The results of the execution are
Copy Code code as follows:
22:27 $ java Testmain
A String instance in Subcaller
The above code, caller, has an implementation of the Call method, Subcaller inherits caller, and overrides the call method implementation. We declare a variable callersub of the caller type, but this variable points to a Subcaller object. It can be seen from the results that it invokes the Subcaller call method implementation rather than the caller calling method. This result is due to dynamic binding at runtime and the need to determine which version of the call method is implemented during the binding process.
Verify
Using JAVAP does not directly validate dynamic binding, and then if it proves that there is no static binding, then the dynamic binding is indicated.
Copy Code code as follows:
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
}
As the result above, 18:invokevirtual #6//Method Testmain$caller.call: (ljava/lang/string;) v This is Testmain$caller.call, not testmain$. Subcaller.call, because the compilation period cannot determine whether the invocation subclass or the parent class is implemented, it can only be thrown at run-time dynamic binding.
When the overload encounters an override
The following example is a bit perverted ha, there are two overloads of the call method in the caller class, more complex Subcaller integration caller and rewriting both methods. In fact, this situation is the combination of the above two situations.
The following code begins with a static binding, determines the call method that invokes the parameter as a string object, and then dynamically binds at run time to determine whether the execution subclass or the call implementation of the parent class occurs.
Copy Code code as follows:
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 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 Subcaller");
}
}
}
Execution results are
Copy Code code as follows:
22:30 $ java Testmain
A String instance in Subcaller
Verify
Since the above has been introduced, here only the reverse compilation results
Copy Code code as follows:
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
}
Curious questions
Not dynamic binding?
In theory, the binding of some methods can also be implemented by static bindings. Like what:
Copy Code code as follows:
public static void Main (string[] args) {
String str = new string ();
Final Caller callersub = new Subcaller ();
Callersub.call (str);
}
For example, where Callersub holds Subcaller objects and Callersub variable is final, the call method is executed immediately, and the compiler theoretically has enough parsing code to know that the calling method should be called Subcaller.
But why is there no static binding?
Suppose our caller inherits from the Basecaller class of a framework that implements the call method, and Basecaller inherits from Supercaller. The call method is also implemented in Supercaller.
Suppose the Basecaller and Supercaller in a frame 1.0
Copy Code code as follows:
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");
}
}
And we use Framework 1.0 for this implementation. Caller inherits from Basecaller and calls the Super.call method.
Copy Code code as follows:
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 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 Subcaller");
}
}
}
Then we compiled the class file based on the 1.0 version of the framework, assuming that the static binding can be used to determine the Super.call for Basecaller.call implementation above caller.
Then again we assume that the framework 1.1 version of Basecaller does not rewrite the Supercaller call method, then the above assumption can be statically bound call implementation in the 1.1 version of the problem, because in the 1.1 version Super.call should be using the Supercall call Method implementation, rather than assuming a basecaller call method that is determined using static bindings.
So, some of the actual can be statically bound, considering security and consistency, simply all of the dynamic binding.
The optimized revelation?
Because dynamic binding requires the runtime to determine which version of the method implementation or variable is to be executed, it is time-consuming than static binding.
So without affecting the overall design, we can consider using private,static or final to modify the method or variable.