在理解这个之前,首先我们需要知道:在JVM中,方法的调用过程
这里的方法调用并不指方法中的代码被执行,而是指确定被调用方法的版本 (即调用哪一个方法)
方法的调用分为两个阶段,分别是解析阶段和分派阶段
1. 解析阶段
也就是我们在Java基础中了解的前期绑定,或者说静态绑定,指代的是在编译期间就能够确定执行的是哪个方法
分类
- final修饰的方法
- static修饰的方法
- private修饰的方法
- 构造方法
2. 分派阶段
也就是后期绑定,或者说动态绑定,指代的是在运行期间才能够确定执行的是哪个方法
注意:分派本身就具有动态性
步骤
- 提取对象的实际类型的方法表
- 搜索方法签名
- 调用方法
相关概念
- 方法表:方法表是一组对类实例方法的直接引用(包括从父类继承的方法),jvm可以通过方法表快速激活实例方法。可以理解为方法表就是一个维护各个方法的数据结构,帮助我们快速找到对应的方法
- 方法签名:方法名 + 方法参数,通过方法签名可以唯一确定一个方法。注意:方法的返回值不属于方法签名
分类
-
根据进行的阶段分类,可分为编译期进行的静态分派和运行期进行的动态分派
-
根据分派基于宗量的多少,可分为单分派和多分派
相关概念
宗量:方法的接收者和方法的参数统称为方法的宗量(接收者是一个宗量,参数是一个宗量)
1. 静态分派
静态分派就是依赖静态类型来定位方法执行版本,在编译阶段确定
相关概念
静态类型和实际类型:以Human man = new Man();为例,Human就是静态类型,Man就是实际类型
典型应用就是方法重载
看不懂没关系,接下来我们举例说明:
public class Test {
// 父类
static class Human {
}
// 两个子类
static class Man extends Human {
}
static class Woman extends Human {
}
// Test类的3个重载方法:参数类型不同
public void sayHello(Human guy) {
System.out.println("Hello, Human!");
}
public void sayHello(Man guy) {
System.out