理解多态的核心思想:“同一接口,多种实现”
掌握 编译时多态(方法重载) 与 运行时多态(方法重写) 的区别与应用
能够设计支持动态行为的类体系结构
理解多态如何提升代码的可扩展性、可维护性与抽象能力
多态(Polymorphism) 源自希腊语:
poly = many(多)
morph = forms(形态)
定义:在 Java 中,多态指同一个方法调用,在不同对象上表现出不同行为的能力。
现实类比:一个人的多重身份
在公司 → 是“员工”
在家里 → 是“父亲”
在父母面前 → 是“儿子”
同一个人,根据上下文扮演不同角色,执行不同行为。
Person p = new Father();
p.role(); // 输出:"I am a father."
Java 中的多态分为两类:
定义
在同一个类中,存在多个同名但参数列表不同的方法。
注意:仅返回类型不同 不算重载!
重载的条件(满足其一即可)
参数数量不同
参数类型不同
参数顺序不同(当类型不同时)
示例:计算器中的 multiply 方法
class Calculator {
// 重载:整数相乘
int multiply(int a, int b) {
return a * b;
}
// 重载:浮点数相乘
double multiply(double a, double b) {
return a * b;
}
// 重载:三个整数相乘
int multiply(int a, int b, int c) {
return a * b * c;
}
}
public class Main {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.multiply(2, 3)); // 6
System.out.println(calc.multiply(2.5, 3.0)); // 7.5
System.out.println(calc.multiply(2, 3, 4)); // 24
}
}编译器在编译时根据参数类型和数量决定调用哪个方法。
定义
子类重新定义父类中已有的方法,提供特定实现。
重写的规则(必须全部满足)
方法名相同
参数列表完全相同
返回类型相同(或协变返回类型)
访问权限不能更严格(如父类是 public,子类不能是 private)
不能重写 static、final、private 方法
核心机制:动态方法分派
JVM 在运行时根据实际对象类型决定调用哪个方法。
示例:动物发声系统
// 父类
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
// 子类
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows");
}
}
// 主程序
public class Main {
public static void main(String[] args) {
Animal a;
a = new Dog();
a.sound(); // 输出:Dog barks
a = new Cat();
a.sound(); // 输出:Cat meows
}
}关键点:
引用类型是
Animal实际对象是
Dog或CatJVM 在运行时选择实际对象的重写方法
优势一览
实际应用场景
// 通用绘图系统
void drawShape(Shape s) {
s.draw(); // 无需知道具体是 Circle 还是 Rectangle
}
// 调用
drawShape(new Circle());
drawShape(new Rectangle());未来新增
Triangle类,drawShape()无需改动!
结论:优点远大于缺点,是 OOP 的核心力量。
三者协同:继承提供结构,封装保障安全,多态赋予灵活行为。
始终使用 @Override 注解
防止拼写错误或签名不匹配:
@Override
void sound() { ... }优先面向接口 / 抽象类编程
List<String> list = new ArrayList<>(); // 而非 ArrayList<String> list = ...避免在构造器中调用可重写方法
子类可能未初始化完成,导致空指针等异常。
合理使用多态,避免过度设计
简单场景无需强行引入继承体系。
多态 = 同一操作,多种实现
编译时多态:方法重载(Overloading)→ 参数不同
运行时多态:方法重写(Overriding)→ 子类定制行为
运行时多态依赖 继承 + 方法重写 + 父类引用指向子类对象
多态是实现高内聚、低耦合、易扩展系统的关键
Java 不支持运算符重载(除 + 用于字符串拼接)
为什么方法重载发生在编译期,而方法重写发生在运行期?
如果父类方法是 private,子类定义同名方法,这算重写吗?为什么?
如何利用多态设计一个支持多种支付方式(微信、支付宝、银行卡)的系统?