JVM的方法调用
关键字: 编译时静态多分派,运行时动态单分派
”静态多分派“是指在编译阶段,编译器根据方法接收者以及参数的静态类型来决定选用的方法版本
”动态单分派“是指在运行阶段,只根据方法接收者的实际类型来决定调用的实际方法
方法调用并不等于于方法执行,方法调用阶段唯一的任务就是确定被调用方法的版本(即调用哪一个方法)
在class文件编译的过程中,没有传统编译中的连接过程,也就是说,所有的方法调用在class中都是指向常量池符号引用.
1. 解析(Resolution)
在类加载的解析阶段,会将其中一部分符号引用改成直接引用,但这么做的前提是,在编译阶段,具体要调用的方法的版本就已经确定下来了,这个过程被称为解析(Resolution). 符合这种“编译时确定,运行时不可变”的方法包括以下几种,这些方法都被称为是”非虚方法“, 它们的解析过程是静态的,在编译阶段就被完全确定,在类加载时的解析阶段就会把相应的符号引用变成直接引用.
私有方法(private)
类静态方法(static)
实例构造器(
) 父类方法
final方法
2. 分派(Dispatch)
分派可以是静态的,也可以是动态的(这里的静态和动态是指分派时依据的参数类型是静态类型还是动态类型),根据分派时依据的宗量数不同,又可以分为单分派和多分派;两者结合就得到了静态单分派、静态多分派、动态单分派以及动态多分派等分派类型.
JAVA是一种“编译时静态多分派, 运行时动态单分派”的语言, 这句话的理解包括两个部分:静态/动态, 单分派/多分派;
静态/动态: 静态动态是指在分派时根据方法接收者和参数的哪种类型(静态类型还是动态类型)进行的,如果是根据方法接收者和参数的静态类型决定,那么就被称为是静态分派, 否则就是动态分派
单分派/多分派: 单分派和多分派是根据分派时依据的宗量数来定义的,如果分派时根据多个宗量来确定,那么就被称为是多分派, 否则就是单分派
编译时静态多分派: 在JAVA编译器进行编译时,编译器会同时根据方法接收者以及参数的静态类型选择方法, 静态多分派最直接的例子就是overload(重载)
运行时动态单分派: 在运行时期, JAVA虚拟机会仅根据方法接收者的动态类型选择实际调用的方法, 动态多分派的例子是override(重写)