最重要的区别在于对象的静态和动态类型与对象的引用之间。
说B延伸A,C延伸B。
对象的动态类型(新类型中使用的类型)是其实际的运行时类型:它定义了对象的实际方法。
对象引用(变量)的静态类型是编译时类型:它定义或声明可以在变量引用的对象上调用哪些方法。
变量的静态类型应始终与它引用的对象的动态类型相同或为父类型。
因此,在我们的示例中,静态类型为A的变量可以引用动态类型为A,B和C的对象。静态类型为B的变量可以引用动态类型为B和C的对象。静态类型为C的变量只能引用具有动态类型的对象。动态类型C。
最后,在对象引用上调用方法是静态和动态类型之间的微妙而复杂的交互。(如果您不相信我,请阅读有关方法调用的Java语言规范。)
例如,如果A和B都实现方法f(),并且静态类型为A,而动态类型为C,则调用方法Bf():
B extends A, C extends Bpublic A.f() {}public B.f() {}A x = new C(); // static type A, dynamic type Cx.f(); // B.f() invoked大大简化:首先,使用接收者(类型A)和参数(没有参数)的静态类型来确定该特定调用的最佳匹配(最特定)方法签名,这是在编译时完成的。在这里,这显然是Af()。
然后,在运行时的第二步中,使用动态类型来定位方法签名的实际实现。我们从C类型开始,但是没有找到f()的实现,因此我们上移到B,并且那里有一个与Af()签名匹配的方法Bf()。因此Bf()被调用。
在我们的示例中,我们说方法Bf()覆盖了方法Af()。类型层次结构中覆盖方法的机制称为子类型多态。



