共计 2570 个字符,预计需要花费 7 分钟才能阅读完成。
一、办法调用指令阐明
简要介绍办法调用指令:
invokevirtual、invokeinterface、invokespecial、invokestatic、invokedynamic
简要办法调用介绍
invokevirtual 指令
用于调用对象的实例办法,依据对象的理论类型进行分派(虚办法分派),反对多态。
这也是 Java 语言中最常见的办法分派形式。
invokeinterface 指令
用于调用接口办法,它会在运行时搜寻由特定对象所实现的这个接口办法,并找出适宜的办法进行调用。
invokespecial 指令
用于调用一些须要非凡解决的实例办法,包含 实例初始化办法(结构器)、公有办法和父类办法
。这些办法都是动态类型绑定的,不会在调用时进行动静派发。
invokestatic 指令
用于调用命名类中的类办法(static 办法)
。这是动态绑定的。
invokedynamic 指令
调用动静绑定的办法,这个是 JDK 1.7 后新退出的指令。
用于在运行时动静解析出调用点限定符所援用的办法,并执行该办法。后面 4 条调用指令的分派逻辑都固化在 java 虚拟机外部,而 invokedynamic 指令的分派逻辑是由用户所设定的疏导办法决定的。
二、通过示例代码来领会办法调用指令
接下来咱们通过示例代码拉领会对应的办法指令,看看会有什么不一样?
public class MethodInvokeReturnTest { | |
// 办法调用指令:invokespecial | |
public void invoke1(){// 状况 1:类实例的结构器办法:<init>() | |
Date date = new Date(); | |
Thread t1 = new Thread(); | |
// 状况 2:父类的办法 | |
super.toString(); | |
// 状况 3:公有办法 | |
methodPrivate();} | |
private void methodPrivate(){} | |
} |
接下来咱们把以后的代码编译一下,看看具体的字节码是怎么形容以后办法的?
如果咱们将以后公有办法 methodPrivate 改为 public 润饰的办法就会产生扭转(可重写)
接下来咱们通过示例代码拉领会下一个办法指令,看看会有什么不一样?
public class MethodInvokeReturnTest { | |
// 办法调用指令:invokestatic | |
public void invoke2(){methodstatic(); | |
} | |
public static void methodStatic(){} | |
} |
把以后的代码编译一下,看看具体的字节码是怎么形容以后办法的?
接下来咱们通过示例代码拉领会下一个办法指令,看看会有什么不一样?
public class MethodInvokeReturnTest { | |
// 办法调用指令:invokevirtual | |
public void invoke4(){system.out.println( "he1lo"); | |
Thread t1 = null; | |
t1.run();} | |
} |
把以后的代码编译一下,看看具体的字节码是怎么形容以后办法的?
接下来咱们通过示例代码拉领会下一个办法指令,看看会有什么不一样?
public class MethodInvokeReturnTest { | |
// 办法调用指令:invokeinterface | |
public void invoke3(){Thread t1 = new Thread(); | |
((Runnable)t1).run(); | |
Comparable<Integer> com = null; | |
com.compareTo(123); | |
} | |
} |
把以后的代码编译一下,看看具体的字节码是怎么形容以后办法的?
那么针对于接口里的静态方法与非静态方法,调用之后又会是什么状况呢?
interface AA{public static void method1(){} | |
public default void method2(){} | |
} | |
class BB implements AA{ | |
} | |
public class InterfaceMethodTest{public static void main( string[] args){AA aa = new BB(); | |
aa.method2(); | |
AA.method1();} | |
} |
把以后的代码编译一下,看看具体的字节码是怎么形容以后办法的?
三、通过示例代码来领会办法返回指令
办法调用完结前,须要进行返回。办法返回指令是依据返回值的类型辨别的。
当咱们返回值是 boolean、byte、char、short 和 int 类型采纳 ireturn 示意
当咱们返回值是 float 类型采纳 freturn 示意
当咱们返回值是 double 类型采纳 dreturn 示意
当咱们返回值是援用型采纳 areturn 示意
还有一条 return 指令供申明为 void 的办法、实例初始化办法以及类和接口的类初始化办法应用。
示例指令解说
通过 ireturn 指令,将以后函数操作数栈的顶层元素弹出,并将这个元素压入调用者函数的操作数栈中〈因为调用者十分关怀函数的返回值),所有在以后函数操作数栈中的其余元素都会被抛弃。
如果以后返回的是 synchronized 办法,那么还会执行一个隐含的 monitorexit 指令,退出临界区
最初,会抛弃以后办法的整个帧,复原调用者的帧,并将控制权转交给调用者。
接下来咱们通过示例代码拉领会对应的办法指令,看看是怎么样的?
public class MethodInvokeReturnTest { | |
// 办法的返回指令 | |
public int returnInt(){ | |
int i = 50; | |
return i; | |
} | |
} |
把以后的代码编译一下,看看具体的字节码是怎么形容以后办法的?
接下来咱们通过示例代码拉领会其余办法返回指令,看看会有什么不一样?
public class MethodInvokeReturnTest { | |
// 办法的返回指令 | |
public double returnDouble(){return 0.0;} | |
public string returnstring(){return "hello,wor1d" ;} | |
public int[] returnArr(){return nu1l;} | |
public float returnFloat(){ | |
int i = 10; | |
return i; | |
} | |
public byte returnByte(){return 0;} | |
} |
把以后的代码编译一下,看看具体的字节码是怎么形容以后办法的?