我正在学习cs61b伯克利公开课,并对这个问题感到困惑(问题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
基于其动态类型?
最佳答案
练习的目的是测试您对使用静态和动态类型进行方法分派(dispatch)的理解。
在您的情况下,Java 编译器必须做出两个决定:
- 需要调用
Dog
或Corgi
的方法,以及 - 对于
Corgi
的方法,需要调用哪个重载。
第一个决定是根据调用表达式c.play(d)
的左侧做出的,即c
,即Corgi
。如果 Corgi
进一步子类为 Cardigan
和 Pembroke
,则相应子类的方法将在运行时根据动态类型调用。
编译器只关心c
的静态类型:它需要确保采用Dog
的play
方法在运行时可用。虚拟调用本身由 JVM 根据 c
对象的动态类型执行。
第二个决定,即需要调用哪个重载,也是在编译时完成的。这很重要,因为它在编译时“锁定”决策。这就是为什么正确答案是 "D"
,即使对象 d
具有 Corgi
的动态类型。
关于Java参数具有不同的静态和动态类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49336247/