super()必须是子类构造方法的第一条语句,否则编译报错;它用于显式调用父类构造器,未显式书写时编译器自动插入无参super();super.成员名可访问被覆盖的父类实例成员,但不适用于private或static成员。

super() 必须是子类构造方法的第一条语句
Java 规定,如果子类构造方法中要显式调用父类构造方法,super() 必须出现在第一行;否则编译直接报错 call to super must be first statement in constructor。即使你没写任何 super(),编译器也会自动插入无参的 super() —— 所以一旦父类没有无参构造器,而子类又没显式调用 super(…),就会编译失败。
常见踩坑点:
- 父类只定义了带参构造器(比如
public Parent(String name)),子类构造器里忘了写super(name) - 在
super()前写了变量声明、日志打印甚至this()调用,都会触发编译错误 -
super()和this()不能共存于同一个构造方法中
super.成员名 用于访问被子类覆盖/隐藏的父类成员
当子类定义了与父类同名的字段或方法时,super.fieldName 或 super.methodName() 可以明确访问父类版本。注意:这仅适用于实例成员(非 static),且不能用于 private 成员(编译不通过)。
典型使用场景:
立即学习“Java免费学习笔记(深入)”;
- 子类重写了父类方法,但在新逻辑中仍需复用父类原始行为,例如
@Override public void start() { super.start(); doExtraWork(); } - 子类和父类有同名字段(不推荐但合法),用
super.id区分父类字段,避免歧义 - 接口默认方法被实现类重写后,想从另一个实现类中调用父接口默认逻辑?不行——
super不能用于接口,默认方法需通过接口名引用,如InterfaceName.super.method()(Java 8+)
super 在多层继承中只指向直接父类
super 永远只代表「声明该成员的类的直接父类」,不会跳过一层去访问祖父类。比如 A → B → C,C 中的 super.method() 调用的是 B 中定义或继承来的 method(),哪怕 B 没重写、实际执行的是 A 的实现,语法上仍是调用 B 的可见版本。
这意味着:
- 无法用
super.super.method()访问祖父类方法(语法非法) - 若 B 把 A 的 public 方法改成了 private,C 就彻底无法通过
super访问到原始 A 的实现 - 动态绑定仍生效:如果 B 重写了方法,C 调用
super.method()还是执行 B 的版本,不是 A 的
super 和 this 的本质区别:编译期绑定 vs 运行期对象
super 不是一个对象引用,它只是编译器用来定位「父类中某个成员」的语法符号;而 this 是当前实例的真实引用。所以 super.toString() 并不是“用父类对象调用”,而是告诉编译器:“请忽略当前类的重写,按父类声明去解析这个方法调用”——最终执行的方法仍取决于运行时的实际类型(除非被 final 修饰)。
容易混淆的点:
-
super不能单独使用(比如System.out.println(super);是非法的) -
super.getClass()返回的仍是当前实例的运行时类(比如 C 类实例),不是父类 Class 对象 -
super不能用于静态上下文(如静态方法、静态代码块),因为不依赖实例
super 的非对象本质,这三个地方最容易出错,尤其在重构继承结构或对接遗留代码时。








