第 7 章:多态
学习目标
- 理解多态的本质(同一个调用,不同行为)
- 掌握向上转型和向下转型
- 学会 instanceof 和模式匹配
- 理解多态的实际用途
一、多态三要素
- 继承:子类继承父类
- 重写:子类重写父类方法
- 向上转型:父类引用指向子类对象
java
class Animal {
public void sound() {
System.out.println("动物叫");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("汪汪汪");
}
}
class Cat extends Animal {
@Override
public void sound() {
System.out.println("喵喵喵");
}
}
// 多态
Animal a1 = new Dog(); // 父类引用指向子类对象
Animal a2 = new Cat();
a1.sound(); // 汪汪汪(运行时绑定到 Dog 的实现)
a2.sound(); // 喵喵喵(运行时绑定到 Cat 的实现)二、多态的实际用途
好处:写一段代码,适用于所有子类。
java
public void handleAnimal(Animal animal) {
animal.sound(); // 不管传 Dog 还是 Cat,自动调用对应实现
}
handleAnimal(new Dog()); // 汪汪汪
handleAnimal(new Cat()); // 喵喵喵三、向上转型(自动,安全)
java
Dog dog = new Dog();
Animal animal = dog; // 自动向上转型
animal.sound(); // ✅ 只能调用父类声明的方法
// animal.bark(); // ❌ 编译报错:父类没有 bark四、向下转型(强制,可能失败)
java
Animal animal = new Dog();
// 必须先 instanceof 判断
if (animal instanceof Dog) { // 类型检查
Dog dog = (Dog) animal; // 强制向下转型
dog.bark(); // 现在可以调用子类方法
}⚠️ 坑 1:向下转型前必须
instanceof判断,否则抛ClassCastException:javaAnimal animal = new Cat(); Dog dog = (Dog) animal; // ❌ 运行时 ClassCastException
JDK 16+ 模式匹配(自动转型 + 绑定变量):
java
if (animal instanceof Dog dog) { // 直接绑定变量
dog.bark();
}五、多态的常见应用
1. 数组里放不同子类
java
Animal[] animals = { new Dog(), new Cat(), new Dog() };
for (Animal a : animals) {
a.sound(); // 自动调用各自的实现
}2. 方法参数用父类
java
public double totalArea(Shape[] shapes) { // 传 Shape 子类数组
double sum = 0;
for (Shape s : shapes) {
sum += s.area(); // 多态调用各自的 area()
}
return sum;
}3. 工厂模式基础
java
public static Animal create(String type) {
return switch (type) {
case "dog" -> new Dog();
case "cat" -> new Cat();
default -> throw new IllegalArgumentException("未知类型");
};
}六、字段没有多态
java
class Parent {
String name = "父类";
}
class Child extends Parent {
String name = "子类";
}
Parent p = new Child();
System.out.println(p.name); // 父类(字段不参与多态,看引用类型)⚠️ 坑 2:方法有多态,字段没有多态。如果子类定义了和父类同名字段,父类引用访问的是父类字段。
七、本章小结
| 要点 | 关键 |
|---|---|
| 多态三要素 | 继承 + 重写 + 向上转型 |
| 向上转型 | 子类 → 父类,自动,只能调父类方法 |
| 向下转型 | 父类 → 子类,必须先 instanceof |
| 多态用处 | 参数用父类,自动适配所有子类 |
| 字段无多态 | 字段看引用类型,不看实际对象 |
动手练习
- Shape 多态:抽象
Shape有area(),子类Circle/Rectangle重写,写一个totalArea(Shape[])方法 - Employee 体系:Employee → Manager / Developer,各自有
calculateBonus(),演示多态调用 - instanceof 练习:写一个
describe(Animal a)方法,根据实际类型输出不同信息
下一章:第 8 章:抽象类与接口 →