You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java类继承中编译器如何确定调用的方法?代码示例疑问

Java方法调用的重载与动态绑定问题
class All { /* ... */ }
class Most extends All { /* ... */ }
class Special extends Most { /* ... */ }

class Top {
    public void m( All p ) { System.out.print("A "); }
}

class Middle extends Top {
    public void m( All p ) { System.out.print("M "); }
    public void m( Special p ) { System.out.print("L "); }
}

class Bottom extends Middle {
    public void m( Most p ) { System.out.print("V "); }
    public void m( Special p ) { System.out.print("X "); }
}

class Test {
    public static void run() {

        All all = new All();
        Most most = new Most();
        Special special = new Special();
    
        Top x = new Middle();
        Top y = new Bottom();
        Middle z = new Bottom();
    
        x.m( most );
        x.m( special );
        y.m( all );
        y.m( special );
        z.m( all );
        z.m( most );
    }
}

这段代码运行后输出为 M M M M M M,以下是对相关疑问的解答:

疑问与解答

1. 为何编译器总是调用Middle类的m()方法?

要搞清楚这个问题,得拆分编译期重载解析和运行期动态绑定两个阶段:

  • 编译阶段:编译器只看变量的声明类型来筛选可选方法。比如x声明为Top,Top里只有m(All)这一个方法,所以不管传入Most还是Special(它们都是All的子类,可向上转型),编译器都会把调用绑定到m(All)这个方法签名上。
  • 运行阶段:JVM根据对象的实际类型调用重写的方法。x实际是Middle,Middle重写了m(All);y实际是Bottom,但Bottom没重写m(All),会继承Middle的实现,最终都会调用Middle的m(All)。

2. 为什么x.m(special)不输出L?

x的声明类型是Top,编译时编译器只能看到Top类里的方法,看不到Middle中新增的m(Special)重载方法。它会在Top的方法列表里找能接收Special参数的方法,最终匹配到m(All)(因为Special是All的子类)。到了运行阶段,方法签名已经被编译成m(All),所以只会执行Middle中重写的m(All),输出M而非L。

3. y.m(all)和y.m(special)为何都输出M?

  • y.m(all):y声明为Top,编译时匹配m(All);运行时y实际是Bottom,但Bottom没有重写m(All),会继承Middle的m(All)实现,输出M。
  • y.m(special):和上面逻辑一致,编译时Top只有m(All)能接收Special参数,方法签名确定为m(All);运行时还是调用Middle的m(All),输出M。

内容的提问来源于stack exchange,提问作者Niklas S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 01:39:18