
在java中,`this.print()`始终调用运行时对象的实际类型(即子类)重写后的方法,无法直接通过`this`访问父类版本;必须使用`super.print()`显式调用父类实现,且需避免`super`与`this`混用导致的无限递归。
你遇到的 StackOverflowError 根本原因在于 Java 的动态绑定(dynamic dispatch)机制:所有非 private、非 static、非 final 的实例方法调用都基于实际运行时对象类型,而非声明类型。因此,在 B 类中:
- this.print() 等价于 print(),始终解析为 B.print()(即使该方法内部又调用了 super.doPrint());
- 而 B.print() 中的 super.doPrint() 会进入 A.doPrint(),其中 this.print() 再次触发 B.print() —— 形成闭环调用链:
B.doPrint() → B.print() → A.doPrint() → B.print() → …
这与 C++ 中 A::doPrint() 是静态限定调用(明确指定作用域)有本质区别:Java 不支持 A.print() 这种语法来绕过动态绑定。
✅ 正确解法:用 super.print() 直接调用父类 print() 方法,并重构逻辑以避免跨层级循环依赖。
以下是修正后的可运行示例:
立即学习“Java免费学习笔记(深入)”;
class A {
public void doPrint() {
print(); // 调用当前对象的 print() —— 动态绑定
}
public void print() {
System.out.println("This is A");
}
}
class B extends A {
@Override
public void doPrint() {
// ✅ 正确:直接委托给父类 print 实现
super.print();
// 或者:显式调用父类行为,不依赖 this.print()
// System.out.println("B delegates to A's print");
}
@Override
public void print() {
// ⚠️ 错误示范(会导致递归):
// super.doPrint(); // ❌ A.doPrint() → this.print() → B.print() → ...
// ✅ 推荐:若需复用父类逻辑,应直接调用 super.print()
System.out.print("B: ");
super.print(); // 输出 "B: This is A"
}
}
public class Main {
public static void main(String[] args) {
B b = new B();
b.doPrint(); // 输出 "This is A"
b.print(); // 输出 "B: This is A"
}
}? 关键原则总结:
- super.methodName() 是唯一安全调用父类被重写方法的方式,它绕过动态绑定,强制执行父类版本;
- 永远不要在子类重写方法中,通过 this 或无修饰调用自身或父类中又间接调用自身的同名方法(如 super.doPrint() → this.print() → 当前子类方法);
- 若设计上需要“子类 print 行为由父类 doPrint 统一调度”,应让 doPrint() 成为模板方法(Template Method),将可变部分抽象为 protected abstract void printImpl(),由子类实现,从而彻底解除循环依赖;
- this. 前缀在实例方法中纯属冗余,不改变绑定行为,仅用于区分局部变量/参数,切勿误以为它能“锁定”当前类的实现。
遵循以上规则,即可在 Java 中清晰、安全地实现类似 C++ 的跨层级方法调用语义。










