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

Java动态方法调用疑问:同参数同对象为何调用结果不同?

拆解Java方法调用的重载与重写逻辑

这问题的核心其实是搞懂Java里方法重载(Overload)是编译时确定,而方法重写(Override)是运行时确定的规则,咱们一个个拆解你存疑的四个调用:

先明确所有变量的编译时/运行时类型:

  • A ac = c;:编译时类型是A,运行时实际对象是C
  • A ab = b;:编译时类型是A,运行时实际对象是B
  • AA aac = c;:编译时类型是AA,运行时实际对象是C

1. ac.f(b) → 输出4

编译阶段:ac的类型是A,而A接口只定义了f(A x)这一个方法签名。不管参数b的实际类型是B,编译时只会匹配A里存在的方法,也就是f(A)。
运行阶段:实际对象是C,C重写了f(A x)方法,所以执行C的f(A)实现,输出4。

2. ab.f(b) → 输出1(重点解释)

这是最容易踩坑的点:

  • 编译阶段:ab的类型是A,A里只有f(A x),所以编译时只能绑定到f(A)这个方法签名。
  • 运行阶段:实际对象是B,但B的f(B x)是新增的重载方法,不是对A接口方法的重写——因为A里根本没有f(B x)这个方法签名。所以运行时会执行B中对f(A x)的实现,也就是输出1。

对比b.f(b)输出2的原因:当用B类型的引用调用时,编译时能看到B里的f(B x)重载,会优先匹配参数类型更精确的方法,所以走f(B)输出2。这就是为什么同对象同参数,引用类型不同结果不同的关键——编译时能看到的方法签名不一样。

3. aac.f(b) → 输出5

编译阶段:aac的类型是AA,AA继承A的同时新增了f(B x)方法。参数b是B类型,编译时会匹配到更精确的f(B x)方法签名。
运行阶段:实际对象是C,C实现了AA的f(B x)方法,所以执行C的f(B)实现,输出5。

4. aac.f(c) → 输出4

编译阶段:aac的类型是AA,AA里的方法是f(A x)(继承自A)和f(B x)。参数c是C类型,C是A的子类但不是B的子类,所以编译时只能匹配到f(A x)。
运行阶段:实际对象是C,执行C的f(A)实现,输出4。


核心规则总结

  • 重载:由编译时的引用类型和参数的编译时类型决定,编译器会选择最匹配的方法签名
  • 重写:由运行时的实际对象类型决定,执行该对象对方法的具体实现

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:15:29