Java多态原理
参考
虚方法
- JVM杂记:对多态实现原理、虚方法表、虚方法、静态解析、动态链接的一些思考_多态和方法表的关系-CSDN博客
静态分派与动态分派
- (JVM)Java虚拟机:静态分派 & 动态分派 原理解析 - 掘金
虚方法表
- JVM 栈帧,静态、动态分派以及虚方法表 - 掘金
背景知识
1、静态类型与动态类型
例子
Human a = new Man()
a = new Woman()
静态类型:
变量a的静态类型 = 引用类型 = Human:不会被改变、在编译器可知
动态类型:
变量a的动态类型 = 实例对象类型 = Man:会变化、在运行期才可知
2、虚方法与非虚方法
概念
非虚方法:如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的。这样的方法称为非虚方法。静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法
虚方法:其他方法就叫做非虚方法
理解
不能被重写的方法都是非虚方法
3、静态分派与动态分派
静态分派
概念
根据对象的静态类型来进行分配,即根据变量的静态类型确定执行哪个方法
理解
1、非虚方法的执行都是静态分派
2、在编译成字节码文件的时候,就已经确定调用哪个方法了,所以由编译器来确定
字节码文件中就已经说明了是哪个类的方法,分号后面的就是
3、类加载的时候,在解析阶段符号引用就可以直接转化为直接引用
方法重载
说明
方法重载虽然也用到了虚方法,而且指令也是虚方法指令,但他是静态分派
概念
方法重载(OverLoad) = 静态分派 = 根据 变量 的静态类型 确定执行(重载)哪个方法
细节
类型强转
类型强转实际上是创建一个新对象,而不是修改原有的对象
例子
Person a = new Person()
(Man) a
此时会创建一个新的静态类型为Man的对象。
动态分派
概念
根据对象的动态类型来进行分配
理解
1、使用到多态的地方(使用虚方法 ,方法重载的情况除外)就是动态分派
2、在编译的时候,无法确定是要调用哪个类的方法,只有在运行的时候才能确定,由JVM来确定
3、类加载的时候,在解析阶段无法转化为直接引用,只有在运行时才能解析
方法重写原理
1、运行时调用到虚方法的时候,会去找动态类型,而不是静态类型
2、然后把符号引用转化为直接引用
4、虚方法表
概念
每个类都有一个虚方法表,这个放在方法区中,记录了当前这个类重写的方法,如果没有重写父类的方法,虚方法表中不会记录
背景
当动态分派进行符号引用的转换时,需要去找到实际上需要使用的方法,假如没有重写那么就是调用父类的方法,所以这个判断流程就是使用虚方法表来实现的
作用
加快动态分派时候,符号引用转化为动态引用的过程
流程
1、找到动态类型,查他的虚方法表,有无目标方法
1、有,那就是这个
2、没有,查找他的父类
2、如此循环
理解
多态是实际上就是动态分派