Java虚拟机分派机制与多态特性

Java虚拟机分派机制与多态特性

今天拜读了周志明大佬的神书第三版,在虚拟机字节码执行引擎这一章中看到了分派与多态底层的联系,觉得可以记录一下。
首先什么是多态,多态是java三大特性之一(继承、封装、多态),多态是同一个接口,使用不同的实现,而执行不同的操作。

多态的三个必要条件:

1、继承(extends)
2、重写(子类重写父类的同名方法)
3、父类引用指向子类的对象,如:
子类继承父类,重写父类的方法,当子类对象调用重写的方法时,调用的是子类的方法,而不是父类的方法,当想要调用父类中被重写的方法时,则需使用关键字super。
这里可以看到了重写,还有一个重载这些都是多态性最直观的表现,我们看到的上面这个子类重写父类方法的这个说法大家基本都知道,但是并不知道为什么会产生这个效果,接下来的分派机制就可以解释,这个效果在java虚拟机底层是如何实现的。

分派:“分派”(Dispatch)这个词本身就具有动态性,一般不应用在静态语境之中,这部分原本在英文原版的《Java虚拟机规范》和《Java语言规范》里的说法都是“Method Overload Resolution”,分派是JVM中方法调用的一个分支知识点。

静态分派与重载:

(静态分派:所有依赖静态类型来决定方法执行版本的分派动作,都称为静态分派)
重载大家平时用的很多,下面就把周志明大佬的例子搬出来:
在这里插入图片描述
在这里插入图片描述

重载用得多的各位应该知道这个最后的结果,那么之后就解释为何是这样。
首先明确一个概念:Human man = new Man();这句实例化语句中,Human 称为变量的“静态类型”,后面的“Man”则被称为变量的“实际类型”,静态类型和实际类型在程序中都可能会发送变化,但是静态类型的变化是在使用时发生的。就是说静态类型在编译期就确定了,实际类型实在运行期才能确定的。那么在编译期实际类型就完全是个“薛定谔的猫”.

在代码实例中,大家可以看到定义了两个静态类型相同的类,而使用的重载方法是代码中高亮的方法,我们发现并没有调用man woman的重载方法。这就说明编译器在重载的时候是通过参数的静态类型而不是实际类型。

那么接下来就说说动态分派与重写,我们回到最开始的那个子类重写父类方法的问题上,下面就用一段代码还原案发场景。(在运行期根据实际类型确定方法执行版本的分配过程叫做动态分派)
在这里插入图片描述
在这里插入图片描述

其实大家看到高亮的方法就知道结果该是什么了。很明显,这次是根据变量参数的实际类型来进行方法的调用了。那么是怎么进行调用的呢,我们看一下main()方法的字节码。
在这里插入图片描述

0~8行都是字节码的准备工作,是建立man和woman的内存空间。调用对应的构造器。9-12行是重点,主要是看两个invokevirtual虚方法的指令。可以看出后面的说明,(参数#6是常量池中第6项的常量)这两个虚方法调用的方法指向的都是一样的,但是最后执行的方法不一样,这得说一下invokevirtual指令:(以下说明来自《深入理解Java虚拟机》)
根据《Java虚拟机规范》,
invokevirtual指令的运行时解析过程[4]大致分为以下几步:
1)找到操作数栈顶的第一个元素所指向的对象的实际类型,记作C。
2)如果在类型C中找到与常量中的描述符和简单名称都相符的方法,则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束;不通过则返回java.lang.IllegalAccessError异常。
3)否则,按照继承关系从下往上依次对C的各个父类进行第二步的搜索和验证过程。
4)如果始终没有找到合适的方法,则抛出java.lang.AbstractMethodError异常。

可以看出invokevirtual第一步就是确定运行期确定接受者的实践类型,所以这里并不是将常量池中方法的符号引用解析到直接引用上就结束了,还会根据方法接受者的运行期的实际类型确定执行方法的版本。这就是重写的本质

下面补充一点分派的知识点:单分派与多分派
方法的接收者与方法的参数统称为方法的宗量。根据分派基于多少种分派,将分派分为单分派和多分派。
通过上面的讲解可以看出,静态分派选择目标方法时会基于静态类型、方法参数来确定符号引用转化为直接引用。这是两个宗量,所有静态分派属于多分派。而动态分派只是基于接收者的实际类型,那么只基于一个宗量,所以是单分派

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值