Referring to method calls, I think most people's first reaction is to execute a method Bai, in fact, in the eyes of the virtual machine method call is only to determine which method he is going to call, and the implementation of the method is still a relatively large difference. The operation of any sequence is inseparable from the invocation of methods and the execution of methods, But learning in the JVM: a summary of runtime stack frames in a virtual machine (ii) mentioned, the traditional connection step (connection: Converting a symbolic reference to a direct reference that can directly find the method body) is not included in the compilation of the class file, but it also gives Java greater flexibility, Because different implementations may transform symbolic references at different stages, the following are descriptions of several common method invocation types
parsing:
In the JVM learning process: The runtime stack frame in a virtual machine mentions that if a symbolic reference is converted to a direct application during class loading or first use, then what kind of method will be converted at this stage? Virtual machine specification mentions that It is only possible to determine the version of the call before it is actually run, and to be immutable at runtime, simply, not to be overwritten. A method that cannot be changed, which cannot be overloaded, is actually the static method, the private method, the final method,<init> constructor , the parent class method, which is suitable for converting a symbolic reference to a direct reference in the class load parsing phase, is called parsing . Other methods of these methods are also called virtual methods ()
Several methods were mentioned earlier, and the virtual machines provided the corresponding bytecode instructions, respectively:
Invokestatic: Calling a static method
Invokespecial: Calling constructor methods, private methods, and parent class methods
Invokevirtual: Invoke the virtual method and the final method (although called with invokevirtual, but is also a non-virtual method because the final method is not covered) Invokeinterface: Calling an interface method, A specific implementation method is determined at runtime
The following is the result of a demo class that validates the bytecode instructions above:
Package com.eric.jvm.executor; /** * Invokestatic: Invoke static method * Invokespecial: Invoke constructor method, private method, and parent class method * Invokevirtual: Invoke virtual Method and final method (although using Invokev Irtual calls, but because the final method is not covered, and therefore is not a virtual method) * Invokeinterface: Calls the interface method, and then determines a specific implementation method at run time * * * Javap-verbose Com.eric.jvm.ex Ecutor. Invokecommandexecutor * * @author Eric * */public class Invokecommandexecutor {public static void main (String
[] args) {//invokestatic subinvoker.invokestatic ();
Invokespecial, Subinvoker si=new subinvoker ();
Invokevirtual si.invokevirtual ();
Invokeinterface Si.invokeinterface (); Class Subinvoker implements iexecutor{public static void Invokestatic () {System.out.println ("invokestatic is E
Xecute ");
Public Subinvoker () {System.out.println ("invokespecial is execute in construct");
};
public void invokevirtual () {System.out.println ("invokevirtual is Execute"); @Override public void Invokeinterface () {System.out.println ("Invokeinterface is exEcute ");
} interface iexecutor{public void Invokeinterface ();}
Decompile related instruction fragment: corresponding to the method call order in main
Assign:
As we all know, object-oriented three features are: "Inheritance, encapsulation, polymorphism", where polymorphism also includes overrides and overloads, the allocation mentioned in this section is the underlying implementation base of overlay and overload. So let's see what the assignment is? The concept of dispatch and resolution, which belongs to the same category, is the type of method invocation, Only the allocation is slightly more complex than parsing, the assigned symbolic application can be converted in the class loading phase, can also be converted at runtime, and there may be a single volume and a number of volumes depending on the volume, each of which is described in the following categories:
Static Dispatch (overload):
Static dispatch can be considered Java is the most fundamental reason to achieve overload, first of all let us look at an example of overload (in writing this article I still failed to guess the correct output, it is sad ah ...)
Package com.eric.jvm.executor;
public class Methodoverloadresolution {public
static void Main (string[] args) {
Human Human = new Human ();
Human mans = New Man ();
Human women = new Women ();
Methodoverloadresolution mor = new Methodoverloadresolution ();
Mor.hello (human);
Mor.hello (mans);
Mor.hello (women);
Static type Changes
Mor.hello ((man) mans);
Mor.hello ((Women) Women);
}
public void Hello (Human Human) {
System.out.println ("Human say hello");
}
public void Hello (Mans human) {
System.out.println ("Man Say Hello");
}
public static void Hello (Women human) {
System.out.println ("Women say hello");
}
Class Human {}
class Man extends Human {}
class Women extends Human {}
The result of its output is
Human Say hello
Human say hello Human say hello man
say hello
Women say hello
I think a regular interviewer can get a good guess at the correct output, but if you ask me why it's possible that a lot of people can't answer it, I'm going to explain why I output the above results.
Human mans = New Man ();
Let's look at two more important concepts, human is a static type, the man is a dynamic type, the static type is determined during compilation, and the overload of the virtual machine is determined by the static type class, so in the compile phase, the virtual machine has decided which version of the method to use is the output of 3 human The reason for say hello.
Depending on the static type class to determine the method version of the dispatch action method is called static dispatch
One of the more important thing about static dispatch is to choose the "best fit" When choosing a method version, and here's an example to see what's best for you:
Import java.io.Serializable; public class Methodoverloaddemonstrate {/** * @param args */public static void main (string[] args) {Methodove
Rloaddemonstrate demonstrate=new methodoverloaddemonstrate ();
Demonstrate.overload (' C ');
public void overload (char c) {System.out.println ("char");}
public void overload (int c) {System.out.println ("int");}
public void overload (long c) {System.out.println ("Long");}
public void overload (float c) {System.out.println ("float");}
public void overload (double c) {System.out.println ("double");}
public void overload (Character c) {System.out.println ("Character");}
public void overload (Serializable c) {System.out.println ("Serializable");}
public void overload (object.. c) {System.out.println ("Object ...");}
public void overload (object C) {System.out.println ("Object");}
public void overload (integer c) {System.out.println ("integer");}
public void overload (Comparable<character> c) {System.out.println ("comparable<character>");} }
When commenting out the public void overload (char c) {System.out.println ("char");} method, the compiler selects public void overload (int c) {System.out.println ("int") instead of an error, as well as commenting out the public void overload (int c) { SYSTEM.OUT.PRINTLN ("int");} , you continue to expand the type, and so on, the order of precedence of the calling method is the Char->int->long->float->double->character-> interface (serilizable)-> Parent class (Object)->object....objs
One thing to note is that because Character extends Object implements Java.io.Serializable, Comparable<character> If the method before the Serilizable type parameter is commented out, because both serializable and compareable<character> are interfaces, they have the same priority, which allows the compiler to not confirm the specific version of the method and rejects the compilation
Dynamic Dispatch (Override):
There is a very close relationship between dynamic dispatch and another important feature of Java, and the following is a simple example to illustrate how the virtual machine implements the Override of the Override.
Package com.eric.jvm.executor;
/**
* The example of override * *
@author Eric * */Public
class Methodoverridedemonstrate {
public static void Main (string[] args) {
methodoverridedemonstrate demonstrate = new Methodoverridedemonstrate (); C9/>parent parent = demonstrate.new parent ();
Parent father = Demonstrate.new father ();
Parent mother = demonstrate.new mother ();
Parent.printinfo ();
Father.printinfo ();
Mother.printinfo ();
}
Class Parent {public
void Printinfo () {
System.out.println ("Parent output ...");
}
Class Father extends Parent {public
void Printinfo () {
System.out.println ("Father output ...");
}
class Mother extends Parent {public
void Printinfo () {
System.out.println ("Mother output ...");
}
}
}
Output
Parent output ....
Father output ....
Mother output ....
Because static dispatch determines the method version through a static type class, it can be inferred that dynamic dispatch determines the method version based on the dynamic type class, and more specifically because the Printinfo () method in the example is a virtual method. Virtual machine directives that execute virtual methods are invokevirtual. And the execution of the instruction is as follows, thus, the importance of dynamic type to override
Single dispatch, multiple dispatch
The parameters for the recipient of the method and the method of the method are collectively referred to as the volume. A single dispatch is a method of determining execution with one volume, and multiple allocations are used to determine the method to be executed in multiple ways.
Package com.eric.jvm.executor;
public class Singlemultidispatch {
/**
* Demo single dispatch, multiple dispatch
*
* @param args
/public static void main ( String[] args) {
parent parent=new parent ();
Parent son=new Son ();
Parent.buy (New IPhone ());
Son.buy (New Sumsung ());
}
Static class parent{public
void Buy (iphone ipphone) {System.out.println ("Parent-buy iphone");
public void Buy (Sumsung Sumsung) {System.out.println ("parent buy Sumsung");}
Static class Son extends parent{public
void Buy (iphone ipphone) {System.out.println ("Son buy iphone");
public void Buy (Sumsung Sumsung) {System.out.println ("son buy Sumsung");}
Static class Sumsung {}
static class IPhone {}
}
The method selection process (static dispatch) of the compile phase is to determine the static type based on the static type, and then to decide the dynamic type based on the parameter, so the static assignment is the multiple dispatch
Runtime virtual machine selection process (dynamic dispatch), first in the compile phase to determine the method signature bit buy (Sumsung), so this time the parameters have been determined, the only uncertainty is the actual recipient of the method, so there is only one volume, that is, dynamic allocation for the single allocation