Java 多态机制深度解析:虚方法、向上转型与动态分派
多态是面向对象三大特性之一,指同一操作作用于不同对象产生不同行为。Java 中通过向上转型(父类引用指向子类对象)和动态方法分派实现。
多态核心概念
- IS-A 测试:对象通过多个 IS-A 检查即为多态(如 Deer IS-A Animal、IS-A Vegetarian、IS-A Object)
- 引用变量:类型固定,但可指向同类型或子类型对象
- 方法调用:编译期看引用类型,运行期看实际对象类型
引用赋值示例
interface Vegetarian {}
class Animal {}
class Deer extends Animal implements Vegetarian {}
Deer d = new Deer();
Animal a = d; // 向上转型
Vegetarian v = d; // 接口引用
Object o = d; // 终极父类
// 所有引用指向同一堆对象
虚方法与动态分派
Java 非私有、非静态、非 final 实例方法均为虚方法。调用虚方法时,JVM 根据对象实际类型在运行期决定执行哪个实现(动态分派)。
经典案例:Employee 与 Salary
class Employee {
void mailCheck() { System.out.println("Employee 邮寄支票"); }
}
class Salary extends Employee {
double salary;
@Override void mailCheck() {
System.out.println("Salary 邮寄支票,薪资: " + salary);
}
}
public class Demo {
public static void main(String[] args) {
Salary s = new Salary(); s.salary = 3600;
Employee e = new Salary(); e.salary = 2400; // 向上转型
s.mailCheck(); // 编译期/运行期均为 Salary.mailCheck
e.mailCheck(); // 编译期 Employee.mailCheck,运行期 Salary.mailCheck
}
}
输出:
Salary 邮寄支票,薪资: 3600.0 Salary 邮寄支票,薪资: 2400.0
多态的三个必要条件
- 继承/实现:子类 extends 父类或 implements 接口
- 重写:子类重写父类虚方法
- 向上转型:父类/接口引用指向子类对象
静态绑定 vs 动态绑定
| 绑定类型 | 时机 | 适用方法 | 示例 |
|---|---|---|---|
| 静态绑定 | 编译期 | private、static、final、构造器 | 方法重载 |
| 动态绑定 | 运行期 | 普通实例方法(虚方法) | 方法重写 |
多态的实际价值
- 可扩展性:新增子类无需修改使用父类引用的客户端代码(开闭原则)
- 统一接口:集合存储父类类型,遍历统一调用
- 策略模式基础:运行时切换算法实现
集合多态示例
List zoo = List.of(new Dog(), new Cat(), new Bird());
for (Animal a : zoo) a.makeSound(); // 各自发出不同声音
注意事项
- 字段不具备多态性:访问的是引用类型声明的字段(静态绑定)
- 静态方法不参与多态:属于类,非对象
- 私有方法不可见,子类定义同名方法属新方法非重写
- 构造器调用链中调用可重写方法有风险(子类字段未初始化)
java
- 精通 Java 运算符:类型、语法与实战示例
- Java 注释:类型、用法与最佳实践
- 精通 Java 增强 for 循环:语法、示例与最佳实践
- 精通 Java 字符串:创建、方法与最佳实践
- 精通 Java 接口:概念、实现与最佳实践
- 精通 Java 匿名内部类:定义、语法与实战示例
- 精通 Java Try-With-Resources:自动资源管理详解
- Java 注解详解:类型、放置位置与实战示例
- Java 断言实战指南:尽早发现 Bug 与保障代码可靠性
- 深入理解 Java Vector:用法、特性及与 ArrayList 的对比
- Java 多态机制深度解析:虚方法、向上转型与动态分派
- Java 封装机制:数据隐藏、访问控制与不变量保护