1. 简介
本文深入讲解 Java 中的 super
关键字。
✅ super
的核心作用是访问父类成员 —— 包括构造器、变量和方法。这是继承机制中非常关键的一环,尤其在处理类的层次结构时,掌握 super
的用法能避免不少“踩坑”。
我们接下来从构造器、成员变量、方法重写三个维度,逐一剖析 super
的实际应用场景。
2. super 与构造器
在子类构造器中,可以通过 super()
调用父类的构造方法。⚠️ 必须放在构造器的第一行,否则编译报错。
比如,我们有一个父类:
public class SuperBase {
String message;
public SuperBase(String message) {
this.message = message;
}
}
子类通过 super(message)
显式调用父类带参构造器:
public class SuperSub extends SuperBase {
public SuperSub(String message) {
super(message); // 调用父类构造器
}
}
当我们实例化子类时:
SuperSub child = new SuperSub("message from the child class");
执行流程如下:
new SuperSub(...)
触发子类构造器- 子类构造器第一行执行
super(message)
,跳转到父类构造器 - 父类完成初始化后,再回到子类继续执行
📌 注意:如果你没写 super()
,编译器会自动插入 super()
调用父类无参构造器 —— 所以父类必须有无参构造器,否则报错。
3. 访问父类成员变量
当子类和父类存在同名成员变量时,子类会“遮蔽”(shadow)父类的变量。此时想访问父类的原始变量,就必须使用 super
。
定义父类:
public class SuperBase {
String message = "super class";
public SuperBase(String message) {
this.message = message;
}
}
子类定义了同名变量:
public class SuperSub extends SuperBase {
String message = "child class";
public void getParentMessage() {
System.out.println(super.message); // 显式访问父类变量
}
public void getChildMessage() {
System.out.println(this.message);
}
}
调用示例:
SuperSub child = new SuperSub("custom message");
child.getParentMessage(); // 输出: custom message(因为构造器已修改父类 message)
child.getChildMessage(); // 输出: child class
✅ 关键点:super.message
指向的是父类中的 message
,即使它被子类同名变量遮蔽。
4. super 与方法重写
当子类重写了父类方法后,如果仍想调用原始的父类实现,就可以用 super.methodName()
。
先看父类定义:
public class SuperBase {
String message = "super class";
public void printMessage() {
System.out.println(message);
}
}
子类重写 printMessage()
,并在构造器中同时调用父类和子类版本:
public class SuperSub extends SuperBase {
String message = "child class";
public SuperSub() {
super.printMessage(); // 调用父类方法
printMessage(); // 调用子类重写后的方法
}
@Override
public void printMessage() {
System.out.println(message);
}
}
输出结果:
super class
child class
✅ 典型应用场景:
- 在子类构造器中初始化前先调用父类逻辑
- 子类增强父类方法(如日志、校验)后,再调用
super.method()
执行原逻辑
⚠️ 注意:super
调用的是直接父类的方法,不会动态绑定到更上层,所以它是“静态”的调用。
5. 总结
super
是 Java 继承体系中的核心关键字,主要用途包括:
- ✅ 在子类构造器中调用父类构造器(必须第一行)
- ✅ 访问被子类遮蔽的父类成员变量
- ✅ 调用被重写的父类方法,实现逻辑复用或增强
📌 常见踩坑点:
- 忘记父类无参构造器导致子类编译失败
- 在静态上下文中误用
super
- 误以为
super.method()
会动态绑定 —— 实际是静态绑定到父类
完整示例代码已托管至 GitHub:
👉 https://github.com/javaguide/tutorials/tree/master/core-java/core-java-oop-inheritance