我的问题是为什么下面的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是合理的。
答案 0 :(得分:1)
方法
public void proc(Z p) {System.out.println(39);}
Z
中的不会覆盖
public void proc(X p) {System.out.println(43);}
<{1>}中的因为它将域限制为X
而不是Z
。
但是,X
中的类似方法会覆盖Y
中的proc
。
由于X
的编译时类型是x
,因此唯一的方法签名就是X
匹配x.proc(z)
是public void proc(X p)
的匹配项。只有现在才进行动态调度,并且选择并执行来自Y
的覆盖版本,这将导致输出&#34; 57&#34;,如预期的那样。
答案 1 :(得分:0)
首先,编译器首先选择在编译时调用哪个方法(带签名)。通过方法解析要调用的签名,考虑变量的编译时类型;多态在这里不适用。编译时类型x
是X
,即使它在运行时确实是Z
对象。只有proc(X)
被认为是匹配的,因为您传入的z
是X
。
在运行时,Java中的多态性意味着要考虑调用该方法的对象的运行时,以确定要调用的覆盖。 Y
proc
会覆盖X
proc
。但是,Z
的{{1}}方法需要proc
,而不是Z
,因此X
Z
方法重载 proc
;它不覆盖它。因此,选择了proc
&#39; Y
。
答案 2 :(得分:0)
这是因为你没有覆盖 proc
方法,但你重载 - 这意味着你正在创建另一个具有相同名称但不同参数的方法列表。
将使用最合适的方法。