Java中正确调用父类被重写方法的实现方式

在java中,`this.print()`始终调用运行时对象的实际类型所对应的重写方法,无法直接通过`this`访问当前类声明的版本;若需调用父类中被重写的同名方法,必须显式使用`super.print()`——但仅限于**直接父类的同名方法**,且不能用于间接调用父类的其他方法(如`super.doprint()`中又调用`this.print()`仍会触发重写)。

你遇到的 StackOverflowError 根本原因在于 Java 的动态绑定(Dynamic Method Dispatch)机制:this.print() 永远解析为当前对象实际类型的 print() 实现,而非声明类型的。在你的示例中:

  • B b = new B(); b.doPrint(); → 调用 B.doPrint()
  • B.doPrint() 中执行 this.print() → 由于 this 是 B 实例,调用 B.print()
  • B.print() 中执行 super.doPrint() → 调用 A.doPrint()
  • A.doPrint() 中执行 this.print() → 再次调用 B.print()(因为 this 仍是 B 实例)

从而形成无限递归:B.print() → A.doPrint() → B.print() → …

✅ 正确解法:若目标是让 B.print() 行为等价于 “执行 A 类原始的 print() 输出”,应直接委托给 super.print(),而非通过 super.doPrint() 间接调用:

class A {
    public void doPrint() {
        this.print(); // 动态绑定:对 B 实例即调用 B.print()
    }

    public void print() {
        System.out.println("This is A");
    }
}

class B extends A {
    @Override
    public void doPrint() {
        this.print(); // 同样动态绑定 → B.print()
    }

    @Override
    public void print() {
        super.print(); // ✅ 关键修正:直接调用 A.print(),不经过 doPrint
    }
}

运行结果:

This is A

⚠️ 注意事项:

  • super.xxx() 只能调用直接父类中定义的方法(或字段),不能跳过父类调用祖父类;
  • super 不能用于静态上下文(如静态方法)、构造器外的 this 引用,也不能在 static 方法中使用;
  • 若需更灵活的控制流(例如 B 中想复用 A 的 doPrint 逻辑但绕过其 print() 重写),应重构设计:将可变行为抽取为模板方法(Template Method Pattern),例如:
class A {
    public final void doPrint() { // final 防止子类覆盖流程
        printImpl(

); } protected void printImpl() { System.out.println("This is A"); } } class B extends A { @Override protected void printImpl() { System.out.println("This is B"); } }

这种设计明确分离了“算法骨架”与“可变行为”,避免了调用链歧义,是 Java 中更健壮、符合面向对象原则的实践方式。