0%

Java方法调用

序言

返景入深林,复照青苔上。

前一阵分析Jimple文件,看到好多种invoke语句,今天来复习一下。

两种链接

静态链接

当一个class文件被装进JVM内部时,如果被调用的目标方法在编译期可知,且运行时保持不变。

动态链接

如果调用的方法在编译器无法确定下来,只能在运行期间确定下来(重写/多态/继承)。

两种方法

非虚方法

静态方法static,私有方法privatefinal方法,构造器<init>,父类方法super.xx()

虚方法

多态,重写,重载。

五种invoke

invokestatic

调用静态方法static,解析阶段唯一确定方法的版本。

invokespecial

调用促使构造器方法<init>,私有方法private,父类方法super.xx()

解析阶段确定唯一方法的版本。

invokevirtual

虚方法,以及final方法。

invokeinterface

调用xx接口

invokedynamic

动态解析出需要调用的方法,然后执行。

lambda表达式。

说明

  1. 非虚方法:invokestatic,invokespecial
  2. 虚方法:invokevirtual,invokedynamic
  3. 特殊说明:final方法其实很特殊,他是唯一一个invokevirtual,却仍然是非虚方法。
  4. invokedynamic主要还是应用于lambda表达式,比较少见

实例

父类Father:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Father{
public Father(){
System.out.println("Father init method.");
}
public static void showStatic(String str){
System.out.println("Father static method."+str);
}

public final void showFinal(){
System.out.println("Father final method.");
}
public void showCommon(){
System.out.println("Father common method.");
}
}

子类Son继承了Father父类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Son extends Father{
public Son() {
super();
}
public Son(int age){
this();
}
public static void showStatic(String str){
System.out.println("Son staitc method."+str);
}
private void showPrivate(String str){
System.out.println("Son private method"+str);
}
public void show(){
showStatic("niceday");
Father.showStatic("good");
showPrivate("hello");
super.showCommon();
super.showFinal();
}

public static void main(String[] args) {
Son son = new Son();
son.show();
}
}

说明:

  1. 重点还是各种方法的调用。
  2. 第一个showStatic("niceday")是Son子类自己的static方法。
  3. 第二个Father.showStatic("good"),是父类的static方法。
  4. 第三个showPrivate("hello"),是子类自己的private方法。
  5. 第四个和第五个方法都是继承父类的方法,分别是父类的正常方法和父类的final方法。

下面看一下字节码,对应关系如下:

image-20200802181946768

image-20200802182209486