Java 继承
继承是面向对象三大特性之一:子类可以复用父类的属性和方法,并在此基础上扩展或改写。它让代码"一次编写、处处复用",也让类与类之间形成清晰的层次。本节重点讲清 extends 语法、super 的用法,以及继承中的构造链。
extends 语法
用 extends 关键字让一个类继承另一个类:被继承的叫父类,继承者叫子类。子类自动拥有父类非 private 的成员:
class Animal { // 父类
void eat() { System.out.println("吃东西"); }
}
class Dog extends Animal { // 子类
void bark() { System.out.println("汪汪叫"); }
}
// —— 片段需放进 main 方法中运行 ——
Dog d = new Dog();
d.eat(); // 父类方法直接可用
d.bark();
// 输出:吃东西
// 输出:汪汪叫
继承的特性
- 单继承:一个类只能有一个直接父类,extends 跟两个类会编译报错。
- 传递性:A 继承 B、B 继承 C,则 A 拥有 B、C 的全部可继承成员。
- Object 根类:任何类都直接或间接继承 java.lang.Object,自带 toString()、equals() 等方法。
- private 成员不参与继承,但可通过父类的公开方法间接访问。
super 与构造链
创建子类对象时,先执行父类构造、再执行子类构造,形成从 Object 到子类的"构造链"。子类构造第一行其实隐式调用了 super()(父类无参构造):
class Animal {
Animal() { System.out.println("Animal 构造"); }
}
class Dog extends Animal {
Dog() { System.out.println("Dog 构造"); }
}
// —— 片段需放进 main 方法中运行 ——
new Dog(); // 先父类后子类
// 输出:Animal 构造
// 输出:Dog 构造
若父类没有无参构造,子类构造必须显式写 super(参数),且 super() 必须位于第一行,否则编译报错:
class Animal {
Animal(String name) { System.out.println("动物:" + name); }
}
class Dog extends Animal {
Dog() { super("旺财"); } // 显式调用父类带参构造
}
super 调用父类方法
子类重写(Override)方法后,可以用 super.方法名() 先执行父类逻辑,再补充自己的部分:
class Animal {
void speak() { System.out.println("动物叫"); }
}
class Dog extends Animal {
@Override void speak() {
super.speak(); // 先调用父类版本
System.out.println("狗:汪汪");
}
}
// —— 片段需放进 main 方法中运行 ——
new Dog().speak();
// 输出:动物叫
// 输出:狗:汪汪
protected 访问
protected 成员在同包内任何类都能访问;跨包时只有子类内部可访问,外部对象不行。它适合"留给子类扩展、不让外人乱动"的成员。
组合与继承怎么选
继承表示 is-a(狗是一种动物),组合表示 has-a(汽车有一台引擎)。组合更灵活、耦合更低,应优先考虑;只有确实是 is-a 且要复用父类接口时才用继承。
super 贯穿继承始终:super() 串起从父类到子类的构造链,super.方法() 复用父类实现。弄清构造顺序与重写规则,继承才能帮你写出清晰、可扩展的类体系。