继承与多态
约 1177 字大约 4 分钟
布欧-Lewyon
2026-05-14
继承(inheritance)与多态(polymorphism)是面向对象的两大核心机制。本节介绍 extends、super、方法重写、final 关键字以及多态的运行时行为。
继承:extends
继承是 OO 中"is-a"关系的代码表达:子类继承父类的非 private 成员(字段与方法),并在此基础上扩展或改写行为。继承有两个核心用途:复用(子类直接使用父类的字段与方法,避免重复编写)和多态的基础(子类可通过重写改变父类行为,见后文)。
下面定义 Animal 父类与 Dog 子类。注意 Dog 用 extends 继承 Animal,因此可以访问 protected 字段 name,并通过 super(name) 调用父类构造器:
public class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void speak() {
System.out.println(name + " 发出声音");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类构造器,必须放在第一行
}
public void wagTail() {
System.out.println(name + " 摇尾巴");
}
}以下代码演示继承的效果:Dog 既可以使用从 Animal 继承的 speak() 方法,也能调用自己独有的 wagTail():
Dog d = new Dog("旺财");
d.speak(); // 继承自 Animal
d.wagTail(); // 子类独有的方法super 关键字
super(...):调用父类构造器,必须出现在子类构造器第一行。super.method():调用父类被重写的方法,在重写方法内部需要保留父类逻辑时常用。- 如果父类没有无参构造器,子类构造器必须显式调用
super(参数),否则编译报错。
访问修饰符在继承中的影响
| 父类成员修饰符 | 子类能否访问 |
|---|---|
private | ❌ 不可见 |
| 默认(无修饰符) | 同包 ✅ / 不同包 ❌ |
protected | ✅(不同包也可) |
public | ✅ |
方法重写(Override)
子类用与父类相同签名的方法替换父类实现。重写方法上的 @Override 注解不是必需的,但建议加上——编译器会检查签名是否正确匹配。
public class Cat extends Animal {
public Cat(String name) {
super(name);
}
@Override
public void speak() {
System.out.println(name + ":喵喵");
}
}重写的规则:
- 方法名、参数列表必须相同。
- 返回类型可以是父类返回类型的子类型(协变返回类型)。
- 访问权限不能比父类更严格(如父类
protected,子类不得改为private)。 - 父类
final方法不能被重写;static方法不能被重写(但可以隐藏,不推荐)。
多态
多态指父类型引用指向子类对象,调用重写方法时执行的是实际对象类型的方法,而非引用声明类型的方法。
Animal a1 = new Dog("旺财");
Animal a2 = new Cat("咪咪");
a1.speak(); // 实际调用 Dog.speak()
a2.speak(); // 实际调用 Cat.speak()多态使得代码可以针对父类型编写,运行时自动派发到子类实现。典型应用是以父类型作为方法参数或集合元素类型:
public static void letThemSpeak(Animal... animals) {
for (Animal a : animals) {
a.speak();
}
}向下转型与 instanceof
当需要调用子类特有方法时,需先向下转型:
if (a1 instanceof Dog) {
Dog dog = (Dog) a1;
dog.wagTail();
}Java 16 起可用 instanceof 模式匹配简化:
if (a1 instanceof Dog dog) {
dog.wagTail();
}转型前始终用 instanceof 检查类型,否则可能抛出 ClassCastException。
final 在继承中的作用
final类:不能被继承(如java.lang.String、java.lang.Math)。final方法:不能被子类重写。常用于工具类中的敏感逻辑或构造器调用的「模板方法」步骤。final字段:与继承无关,表示值不可变。
小结
- 继承用
extends,子类通过super()调用父类构造器(必须第一行),通过super.method()调用父类被重写的方法。 - 方法重写要求签名相同、访问权限不缩小、返回类型协变;
@Override注解可防手误。 - 多态使父类型引用调用子类重写方法,是 OO 设计实现"开闭原则"的基础手段。
- 向下转型前用
instanceof检查类型,Java 16+ 支持模式匹配语法;转型失败抛出ClassCastException。 final类不能继承,final方法不能重写,合理使用可提升 API 安全性。- 易错:子类构造器中如果父类没有无参构造器,必须显式
super(参数),否则编译不通过。另外,在构造器中不要调用可被重写的方法——此时子类尚未完全初始化。 - 思考任务:定义
Shape→Circle→ColoredCircle三层继承,每层speak()打印不同信息;用父类型变量引用子类对象,观察多态行为。
上一节:内部类与嵌套类型
下一节:抽象类与接口
