Java基础:Java 面向对象编程(OOP)之【继承性】
·
继承(Inheritance) 是面向对象编程(OOP)的四大核心特性之一(其余为封装、多态、抽象),它允许一个类(子类)基于另一个类(父类)来构建,从而复用已有代码、扩展功能、建立类之间的层次关系。
“继承 = 复用 + 扩展”
子类自动拥有父类的属性和方法,并可在此基础上添加新特性或修改已有行为。
一、继承的核心目的
- 代码复用:避免重复编写相同逻辑;
- 建立类间关系:体现“is-a”关系(如“狗 is a 动物”);
- 支持多态:为运行时多态提供基础(父类引用指向子类对象)。
二、Java 中如何实现继承?
1. 语法:使用 extends 关键字
class 父类 {
// 父类成员
}
class 子类 extends 父类 {
// 子类新增或重写的成员
}
2. 示例:动物 → 狗
// 父类
class Animal {
protected String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + " is eating.");
}
}
// 子类
class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类构造器
}
// 新增方法
public void bark() {
System.out.println(name + " is barking!");
}
// 重写父类方法
@Override
public void eat() {
System.out.println(name + " is eating dog food.");
}
}
使用:
Dog dog = new Dog("旺财");
dog.eat(); // 输出:旺财 is eating dog food.
dog.bark(); // 输出:旺财 is barking!
三、继承的关键规则
✅ 1. Java 只支持单继承
- 一个类只能直接继承一个父类(避免菱形继承问题);
- 但可通过接口(interface)实现多继承效果。
// ❌ 错误:Java 不允许多继承
// class A extends B, C { }
// ✅ 正确:通过接口
class A extends B implements C, D { }
✅ 2. 构造器不会被继承,但会调用
- 子类构造器必须调用父类构造器(显式或隐式);
- 若父类无无参构造器,子类必须显式调用
super(...)。
class Parent {
public Parent(String name) { }
}
class Child extends Parent {
public Child() {
super("default"); // 必须显式调用
}
}
✅ 3. 成员访问权限影响继承
private成员:子类不可见(但存在于对象中);protected/public/ 默认(包内):可被继承(受访问控制限制)。
📌 提示:通常将父类字段设为
protected,以便子类安全访问。
✅ 4. 方法可被重写(Override),字段不能
- 子类可重写父类的非 private、非 final、非 static 方法;
- 字段即使同名,也是隐藏(hiding),不是重写。
class Parent {
int value = 10;
}
class Child extends Parent {
int value = 20; // 隐藏父类字段,不是重写
}
四、super 关键字的作用
| 用法 | 说明 |
|---|---|
super() |
调用父类构造器(必须在子类构造器第一行) |
super.method() |
调用父类被重写的方法 |
super.field |
访问父类被隐藏的字段(不推荐,应避免字段隐藏) |
示例:
@Override
public void eat() {
super.eat(); // 先执行父类逻辑
System.out.println("...and wagging tail.");
}
五、继承的适用场景与原则
✅ 适合使用继承的情况:
- 存在明确的 “is-a” 关系(如 Student is a Person);
- 子类确实是父类的特殊化;
- 需要复用并扩展父类行为。
❌ 不适合使用继承的情况:
- 仅为复用代码而强行建立“is-a”关系(违反设计原则);
- 类之间是 “has-a” 关系(应使用组合/聚合)。
🌰 例子:
- ✅
Car继承Vehicle(汽车 is a 车辆)→ 合理;- ❌
Car继承Engine(汽车 has an 引擎)→ 应使用组合:class Car { private Engine engine; }
📜 里氏替换原则(LSP):
子类对象应当能够替换父类对象,且程序行为不变。
如果重写方法后破坏了父类契约,说明继承设计不合理。
六、继承 vs 组合(Composition)
| 对比项 | 继承 | 组合 |
|---|---|---|
| 关系 | is-a | has-a |
| 耦合度 | 高(紧耦合) | 低(松耦合) |
| 灵活性 | 低(编译期确定) | 高(运行时可变) |
| 复用方式 | 代码继承 | 对象持有 |
💡 优先使用组合,而非继承(《Effective Java》建议)
组合更灵活、更安全,避免继承带来的脆弱基类问题。
七、总结:继承的价值与注意事项
✅ 优势:
- 代码复用,减少冗余;
- 建立清晰的类层次结构;
- 为多态提供基础。
⚠️ 注意事项:
- 不要为了复用而滥用继承;
- 遵循“is-a”原则和里氏替换原则;
- 慎用继承,优先考虑组合;
- 父类设计要稳定,否则影响所有子类;
- 避免深层继承链(如 A → B → C → D),增加维护难度。
🙌 感谢你读到这里!
🔍 技术之路没有捷径,但每一次阅读、思考和实践,都在悄悄拉近你与目标的距离。
💡 如果本文对你有帮助,不妨 👍 点赞、📌 收藏、📤 分享 给更多需要的朋友!
💬 欢迎在评论区留下你的想法、疑问或建议,我会一一回复,我们一起交流、共同成长 🌿
🔔 关注我,不错过下一篇干货!我们下期再见!✨
更多推荐



所有评论(0)