贝利信息

Java中正确调用父类被重写方法的完整指南

日期:2026-01-09 00:00 / 作者:花韻仙語

在java中,`this.print()`始终调用运行时对象的实际类型(即子类)重写后的方法,无法直接通过`this`访问父类版本;必须使用`super.print()`显式调用父类实现,且需避免`super`与`this`混用导致的无限递归。

你遇到的 StackOverflowError 根本原因在于 Java 的动态绑定(dynamic dispatch)机制:所有非 private、非 static、非 final 的实例方法调用都基于实际运行时对象类型,而非声明类型。因此,在 B 类中:

这与 C++ 中 A::doPrint() 是静态限定调用(明确指定作用域)有本质区别:Java 不支持 A.print() 这种语法来绕过动态绑定。

✅ 正确解法:用 super.print() 直接调用父类 print() 方法,并重构逻辑以避免跨层级循环依赖。

以下是修正后的可运行示例:

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"
    }
}

? 关键原则总结:

遵循以上规则,即可在 Java 中清晰、安全地实现类似 C++ 的跨层级方法调用语义。