在 Java 面向对象编程中,“继承” 是三大核心特征(封装、继承、多态)之一,它的核心价值是实现代码复用,让子类站在父类的 “肩膀” 上快速扩展功能。今天我们结合实例,从基础概念到实战代码,彻底搞懂 Java 继承的用法与精髓。
一、什么是继承?为什么需要它?
简单来说,继承是类与类之间的 “父子” 关系:子类(派生类)可以继承父类(基类)的属性和方法,同时还能添加自己的特有内容。
举个生活中的例子:“员工(Worker)” 是一个通用概念,而 “厨师(Chef)”“经理(Manager)” 都是 “员工” 的具体类型 —— 他们都有工号、姓名、工资等共性,也有各自的特有工作(炒菜、管理)。这时就可以让Chef和Manager继承Worker,复用共性代码,只关注特有功能。
继承的核心优势:
- 代码复用:将多个子类的共性代码抽离到父类,避免重复编写(比如
Worker中的id、name属性和eat()方法,Chef和Manager无需再定义)。 - 功能扩展:子类可以在父类基础上新增属性或方法(比如
Manager新增了monthlyOverride奖金属性)。
二、继承的基本语法与关系定义
Java 中用extends关键字声明继承关系,语法如下:
// 父类:通用的基类
public class 父类名 {
// 共性属性和方法
}
// 子类:继承父类,拥有父类的内容 + 自己的特有内容
public class 子类名 extends 父类名 {
// 特有属性和方法
}
结合具体的代码示例帮助理解:
// 父类:员工(通用属性和方法)
public class Worker {
private int id; // 工号
private String name; // 姓名
private int wage; // 工资
public void work() { // 通用工作方法
System.out.println("工作");
}
public void eat() { // 通用吃饭方法
System.out.println("吃米饭");
}
// get/set方法、构造方法...
}
// 子类:厨师(继承Worker,新增特有功能)
public class Chef extends Worker {
@Override
public void work() { // 重写工作方法(特有实现)
System.out.println("炒菜");
}
}
// 子类:经理(继承Worker,新增特有功能)
public class Manager extends Worker {
private int monthlyOverride; // 特有属性:月度奖金
@Override
public void work() { // 重写工作方法(特有实现)
System.out.println("管理其他人");
}
// 特有方法:获取奖金
public int getMonthlyOverride() {
return monthlyOverride;
}
}
Worker是父类,Chef和Manager是子类,两者通过extends建立继承关系。- 子类会自动拥有父类的非私有属性和方法(比如
Worker的id、name可通过get/set访问,eat()方法可直接调用)。
三、继承中的核心规则(必知!)
1. 成员变量 / 方法的访问:就近原则
当子类访问属性或方法时,遵循 “就近原则”:
- 先在子类自身找,找到则使用;
- 找不到则去父类找,逐级向上;
- 若父类和子类有同名方法(方法重写),优先使用子类的实现。
比如Chef调用work()时,会优先使用自己重写的System.out.println("炒菜"),而非父类的"工作"。
2. 方法重写:子类的 “个性化改造”
当父类的方法无法满足子类需求时,子类可以重写(Override) 父类方法,定义自己的实现。
方法重写的规则(必须遵守):
- 方法名称、参数列表必须与父类完全一致(比如
work()方法,父类和子类的方法名、参数都相同)。 - 子类方法的访问权限(public/protected 等)必须大于等于父类(比如父类是
public,子类不能是private)。 - 必须加
@Override注解(非强制,但建议加,IDE 会帮你检查是否符合重写规则)。
代码示例中,Chef和Manager都重写了Worker的work()方法,分别实现 “炒菜” 和 “管理其他人”,这就是重写的典型应用。
3. 构造方法:子类必须先初始化父类
父类的构造方法不能被继承,但子类的构造方法会默认先调用父类的无参构造方法(因为子类初始化时可能需要使用父类的属性,必须保证父类先完成初始化)。
关键细节:
- 若父类没有无参构造(比如只定义了有参构造),子类必须在自己的构造方法中显式调用父类的有参构造,用
super(参数)实现。
代码示例:
// 父类Worker的有参构造
public Worker(int id, String name, int wage) {
this.id = id;
this.name = name;
this.wage = wage;
}
// 子类Chef的构造方法:必须显式调用父类有参构造
public Chef(int id, String name, int wage) {
super(id, name, wage); // 调用父类的有参构造,初始化父类属性
}
// 子类Manager的构造方法:同样需要调用父类构造
public Manager(int id, String name, int wage, int monthlyOverride) {
super(id, name, wage); // 先初始化父类属性
this.monthlyOverride = monthlyOverride; // 再初始化自己的特有属性
}
super(...)必须放在子类构造方法的第一行,否则编译报错。
4. Java 继承的限制:单继承、多层继承
- 单继承:一个子类只能有一个直接父类(比如
Chef不能同时继承Worker和AnotherClass)。 - 多层继承:支持 “祖父 - 父 - 子” 的多层继承(比如
Manager继承Worker,Worker可以再继承Person)。
这样设计是为了避免 “多继承” 带来的逻辑混乱(比如多个父类有同名方法时,子类不知道该继承哪个)。
四、实战演示:继承的实际应用
我们通过Test类测试继承的效果,看看子类如何复用父类功能并扩展:
public class Test {
public static void main(String[] args) {
// 创建厨师对象
Chef chef = new Chef(2000, "张三", 4000);
System.out.println(chef.getId()); // 复用父类的get方法:2000
System.out.println(chef.getName()); // 复用父类的get方法:张三
chef.work(); // 调用子类重写的方法:炒菜
chef.eat(); // 复用父类的方法:吃米饭
// 创建经理对象
Manager manager = new Manager(1520, "王五", 6000, 200);
System.out.println(manager.getId()); // 2000
System.out.println(manager.getMonthlyOverride()); // 调用子类特有方法:200
manager.work(); // 调用子类重写的方法:管理其他人
manager.eat(); // 复用父类的方法:吃米饭
}
}
运行结果:
2000
张三
炒菜
吃米饭
1520
200
管理其他人
吃米饭
可以看到:
Chef和Manager无需自己定义id、name等属性,直接通过父类的get方法访问。- 两者都复用了父类的
eat()方法,同时用重写的work()实现了自己的工作内容。 Manager还能通过特有方法getMonthlyOverride()访问自己的monthlyOverride属性。
五、继承的使用场景与注意事项
什么时候用继承?
只有当类与类之间满足 “子类是父类的一种” 的关系时(比如 “厨师是员工的一种”“狗是动物的一种”),才适合用继承。避免为了复用代码而强行继承(比如 “学生” 和 “书” 没有这种关系,不能继承)。
注意事项:
- 私有成员不能直接继承:父类的
private属性 / 方法(比如Worker的id),子类不能直接访问,需通过父类的get/set方法操作。 - 静态方法不能重写:父类的静态方法属于类本身,子类可以继承但不能重写(@Override 会报错)。
- 构造方法不能继承:子类必须通过
super()调用父类构造,保证父类先初始化。
六、总结
继承是 Java 实现代码复用的核心机制,通过extends关键字让子类继承父类的共性,同时扩展特有功能。本文通过 “员工 - 厨师 - 经理” 的实例,讲解了继承的语法、方法重写、构造方法调用等核心知识点。
关键是要理解:继承的本质是 “is-a” 关系,合理使用能大幅减少重复代码,让程序更易维护。下次写代码时,不妨先思考类之间的共性,尝试用继承优化结构~
5万+

被折叠的 条评论
为什么被折叠?



