使用超类引用变量在Java子类对象中重载/覆盖方法
class A{ void m1(A a) {System.out.print("A");} } class B extends A{ void m1(B b) {System.out.print("B");} } class C extends B{ void m1(C c) {System.out.print("C");} } public class d { public static void main(String[] args) { A c1 = new C(); C c2 = new C();c1.m1(c2); }}
此代码的输出为'A'
。
但如果我将A类修改为:
class A{ void m1(C a) {System.out.print("A");} }
那么输出是'C'
。 有人可以解释这段代码是如何工作的?
(通过对参数类型和实现使用相同的inheritance层次结构,您已经使它变得更加混乱。分离它们可能有助于在您的脑海中简化它。)
c1
的类型是A
因此,在确定要调用哪个方法签名时,编译器只能查看在A
声明的方法。
所以在第一种情况下,编译器将调用m1(A)
; 在第二种情况下,编译器将调用m1(C)
。
现在在第一种情况下, m1(A)
方法永远不会被覆盖,因此实际上c1
的执行时类型是无关紧要的。
在第二种情况下, m1(C)
被C
覆盖,因此调用C
的实现是因为c1
的执行时类型是C
所以请记住:
- 根据方法目标和参数表达式的编译时类型,在编译时确定重载分辨率(调用方法签名)
- 该方法签名( 覆盖 )的实现基于执行时目标对象的实际类型。