我正在学习cs61b Berkeley开放课程,并对这个问题感到困惑(问题1,第7行): https://sp18.datastructur.es/materials/discussion/examprep04sol.pdf
c.play(d); // Method D is called
所以在这种情况下,d
的静态类型为Dog
,动态类型为Corgi
,在编译时Method D
中会记录,那么为什么在运行时呢?仍然根据其动态类型调用Method D
而不是Method E
?
答案 0 :(得分:0)
练习的目的是测试你对使用静态和动态类型进行方法调度的理解。
在您的情况下,Java编译器必须做出两个决定:
Dog
或Corgi
,Corgi
的方法,则需要调用哪个重载。第一个决定是基于呼叫表达式c.play(d)
的左侧,即c
,即Corgi
。如果将Corgi
进一步子类化为Cardigan
和Pembroke
,则会在运行时根据动态类型调用相应子类的方法。
编译器只关注c
的静态类型:它需要确保play
方法在运行时可用Dog
。虚拟调用本身由JVM根据c
对象的动态类型执行。
需要调用重载的第二个决定也是在编译时完成的。这很重要,因为它在编译时“锁定”了决策。这就是正确答案为"D"
的原因,即使对象d
的动态类型为Corgi
。