super调用不符合预期:基类方法为何调用派生类重写方法?
Java方法重写中的动态分派问题解析
代码示例
public class A { void someMethod() { System.out.println("Some method from A"); } void someOtherMethod() { System.out.println("Some other method from A"); this.someMethod(); } } public class B extends A { void someMethod() { System.out.println("Some method from B"); } void test() { System.out.println("Test method from B"); super.someOtherMethod(); } } public class Main { public static void main(String[] args) { B b = new B(); b.test(); } }
程序输出
Test method from B Some other method from A Some method from B
现象原因
这是Java动态方法分派的核心特性,也是多态的典型表现:当调用实例方法时,JVM会根据当前对象的实际运行时类型(而非引用的声明类型)来决定执行哪个版本的方法。
在你的代码中,someOtherMethod虽通过super.someOtherMethod()触发,但方法执行时的this仍然指向B类的实例。此时this.someMethod()会触发动态分派,优先执行B类中重写的someMethod,而非A类的原始版本。
实现预期效果的方法
如果想让someOtherMethod固定调用A类自身的someMethod,可以用以下几种方式:
1. 将A类的someMethod设为私有
私有方法无法被子类重写,B类中的someMethod会被视为全新方法,与A类的someMethod无关联。此时A类的someOtherMethod调用的就是自身的私有方法:
public class A { private void someMethod() { // 修改为私有 System.out.println("Some method from A"); } void someOtherMethod() { System.out.println("Some other method from A"); this.someMethod(); } }
2. 将A类的someMethod标记为final
final方法禁止子类重写,无论对象实际类型是什么,调用的都是A类的someMethod:
public class A { final void someMethod() { // 添加final修饰符 System.out.println("Some method from A"); } void someOtherMethod() { System.out.println("Some other method from A"); this.someMethod(); } }
3. 使用私有辅助方法封装核心逻辑
如果需要保留someMethod的可重写性,但希望someOtherMethod固定执行A类的原始逻辑,可以把核心逻辑封装到私有辅助方法中:
public class A { void someMethod() { originalSomeMethod(); } // 私有辅助方法,封装A类的核心逻辑 private void originalSomeMethod() { System.out.println("Some method from A"); } void someOtherMethod() { System.out.println("Some other method from A"); originalSomeMethod(); // 直接调用私有辅助方法 } }
这样即使B类重写了someMethod,someOtherMethod仍然会执行A类的原始逻辑。
内容的提问来源于stack exchange,提问作者user15822443
相关产品推荐
相关产品推荐

