有人可以解释编译器/运行时如何在示例中运行适当的方法吗?有 6 个类和一个void m(/* ... */)具有不同参数的方法。我知道编译器会分析声明的类型。输出总是来自中产阶级的“M”。public class All {}public class Most extends All {}public class Special extends Most {}public class Top { public void m( All p ) { System.out.println("A"); }}public class Middle extends Top { public void m( All p ) { System.out.println("M"); } public void m( Special p ) { System.out.println("L"); }}public class Bottom extends Middle { public void m( Most p ) { System.out.println("V"); } public void m( Special p ) { System.out.println("X"); }}public class Main { public static void main(String[] args) { 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 ); // Output is M x.m( special ); // Output is M y.m( all ); // Output is M y.m( special ); // Output is M z.m( all ); // Output is M z.m( most ); // Output is M }}
1 回答
![?](http://img1.sycdn.imooc.com/5333a0780001a6e702200220-100-100.jpg)
蝴蝶不菲
TA贡献1810条经验 获得超4个赞
方法覆盖在运行时通过查看对象的运行时类型来解决。编译器也决定调用哪个方法,但它只能根据表达式的编译时类型来决定。
对于对 的两次调用x
,它们都Top.m(All)
在编译时解析为。x
是编译时类型Top
,因此编译器只能查找 中声明的方法Top
及其超类。编译器发现唯一可用的方法是m(All)
. 在运行时,要调用的方法被解析为Middle.m(All)
。这是因为运行时类型x
实际上是Middle
,所以运行时将调用覆盖m(All)
在Middle
。为什么不叫Middle.m(Special)
?编译器已经决定Top.m(All)
应该调用。运行时只会检查运行时类型是否覆盖了它。编译器不知道有一个Middle.m(Special)
因为x
是编译时类型Top
。
这两个调用y
是相似的。y
的编译时类型仍然是Top
,因此编译器将方法解析为Top.m(All)
. y
是运行时类型Bottom
。由于Bottom
继承自Middle
,它也覆盖Top.m(All)
。实现与Middle
. 因此在运行时调用被覆盖的方法。
这两个电话z
有点不同,但他们Middle.m(All)
最终还是决心这样做。的编译时类型z
是Middle
,因此两个调用都解析为Middle.m(All)
。请注意,没有Middle.m(Most)
,因此调用z.m(most)
仍将解析为Middle.m(All)
。在运行时,该方法仍然解析为,Middle.m(All)
因为运行时类型Bottom
不会覆盖Middle.m(All)
。
添加回答
举报
0/150
提交
取消