Java中子类必须用super显式调用父类方法,不能自动回退;super仅限非静态上下文,构造器中需首行调用;重写时用super复用父逻辑,避免递归;接口默认方法需InterfaceName.super调用。

子类中用 super 显式调用父类方法
Java 中子类不能直接通过方法名覆盖调用父类同名方法,必须用 super 关键字显式指定。这和 Python 的 super() 类似,但 Java 不支持无参 super 自动推导——必须写全 super.methodName(...)。
常见错误是误以为重写后还能靠名字“自动回退”到父类逻辑,实际不加 super 就只是当前类自己的实现(或编译报错,如果该方法没被重写)。
-
super只能在子类的非静态方法或构造器中使用,不能在静态上下文里出现 - 调用
super.toString()前要确保父类该方法不是private,否则编译失败 - 若父类方法被
final修饰,子类无法重写,但依然可以用super调用它 - 构造器中调用
super(...)必须是第一行语句,否则编译报错:call to super must be first statement in constructor
super 和 this 在方法调用中的分工
super 指向直接父类的成员,this 指向当前实例(可能属于子类类型),二者定位不同。容易混淆的是:当子类未重写某方法时,this.methodName() 实际执行的仍是父类版本,但这不是“调用了父类”,而是动态绑定的结果——此时 this 和 super 表现一致,但机制完全不同。
真正需要 super 的典型场景是:子类重写了方法,但仍需复用父类逻辑(比如日志、校验、初始化)。这时不能写 this.methodName(),否则会触发递归调用(除非你故意想栈溢出)。
立即学习“Java免费学习笔记(深入)”;
- 重写
toString()时常用:return "SubClass[" + super.toString() + ", extra=" + field + "]"; - 重写
equals(Object o)时,应先if (!super.equals(o)) return false;,避免忽略父类字段比较 - 不要在
static方法里写super.xxx(),编译直接拒绝
父类方法被重载而非重写时的调用陷阱
重载(overload)发生在同一类中,参数签名不同;重写(override)才涉及父子类关系。如果父类有 print(String),子类定义了 print(String, int),这不是重写,而是新增重载方法——此时子类里调用 print("a") 仍走父类版本,不需要也**不能**加 super。
但一旦子类也定义了 print(String),就构成重写,此时 print("a") 默认调用子类版;要调父类版,必须写 super.print("a")。
- IDE(如 IntelliJ)常把重载方法标为“inherited”,容易误判为可被
super调用的目标 -
@Override注解只对重写有效,对重载加了也没用,编译器不报错但也不起作用 - 泛型擦除可能导致看似重写的签名实际是重载(比如父类
set(List,子类) set(ArrayList),这种情况下) super.set(...)可能不匹配
接口默认方法与 super 的特殊用法
Java 8+ 接口可含 default 方法,子类实现接口时若也提供了同签名方法,就构成对默认方法的重写。此时可用 InterfaceName.super.methodName() 显式调用特定接口的默认实现——这是唯一允许带前缀的 super 语法。
例如:MyInterface.super.doSomething()。注意这里不能省略接口名,也不能写成 super.doSomething()(那会指向父类,不是接口)。
- 多个接口提供同名 default 方法且未被子类覆盖时,编译报错,必须显式用
InterfaceName.super.xxx()消除歧义 - 类继承父类并实现接口,且三者都有同名方法时,
super.xxx()总是指向直接父类,InterfaceName.super.xxx()才指接口 - 这种带接口名的
super只能在实现类中使用,不能在抽象类或接口内部使用
super 的适用边界、重载/重写的识别、接口默认方法的前缀语法,这几个地方稍不留意就会掉进静默错误或编译失败的坑里。尤其在多人协作或重构时,光看方法名很容易误判调用链。







