不明确的java层次结构
我的问题是为什么下面的x.proc(z)
打印57而不是打印39?
class X { protected int v=0; public X() {v+=10; System.out.println("constr X");} public void proc(X p) {System.out.println(43);} } class Y extends X { public Y() {v+=5;System.out.println("constr Y");} public void proc(X p) {System.out.println(57);} public int getV() {return v;} } class Z extends Y { public Z() {v+=9;System.out.println("constr Z");} public void proc(Z p) {System.out.println(39);} } class Main { public static void main(String argv[]) { X x = new Z(); // v=24 Y y = new Z(); // v=24 Z z = new Z(); // v=24 x.proc(z); //57 } }
X x
指的是Z
对象, Z
类的确有方法proc(Z p)
但它也有方法proc(X p)
。 参数z
也是Z
型,因此打印39是合理的。
方法
public void proc(Z p) {System.out.println(39);}
在Z
中不会覆盖
public void proc(X p) {System.out.println(43);}
在X
因为它将域限制为Z
而不是X
但是, Y
中的类比方法确实覆盖了X
proc
。
由于x
的编译时类型是X
,因此匹配x.proc(z)
的唯一方法签名是public void proc(X p)
。 只有现在才进行动态调度,并且选择并执行来自Y
的覆盖版本,这导致输出“57”,如预期的那样。
首先,编译器首先选择在编译时调用哪个方法(带签名)。 通过方法解析要调用的签名,考虑变量的编译时类型; 多态在这里不适用。 x
的编译时类型是X
,即使它在运行时确实是Z
对象。 只考虑proc(X)
,并且匹配,因为你传入的z
是X
在运行时,Java中的多态性意味着要考虑调用该方法的对象的运行时,以确定要调用哪个覆盖。 Y
的过程优先于X
的过程。 但是, Z
的proc
方法采用Z
而不是X
,所以Z
的proc
方法重载 proc
; 它不会覆盖它。 因此,选择Y
的过程。
因为你没有覆盖 proc
方法,但是你正在重载它 – 这意味着你正在创建另一个具有相同名称但不同参数列表的方法。
将使用最合适的方法。