不明确的java层次结构

时间:2018-03-15 21:56:36

标签: java inheritance polymorphism

我的问题是为什么下面的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是合理的。

3 个答案:

答案 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)

首先,编译器首先选择在编译时调用哪个方法(带签名)。通过方法解析要调用的签名,考虑变量的编译时类型;多态在这里不适用。编译时类型xX,即使它在运行时确实是Z对象。只有proc(X)被认为是匹配的,因为您传入的zX

在运行时,Java中的多态性意味着要考虑调用该方法的对象的运行时,以确定要调用的覆盖。 Y proc会覆盖X proc。但是,Z的{​​{1}}方法需要proc,而不是Z,因此X Z方法重载 proc;它覆盖它。因此,选择了proc&#39; Y

答案 2 :(得分:0)

这是因为你没有覆盖 proc方法,但你重载 - 这意味着你正在创建另一个具有相同名称但不同参数的方法列表。

将使用最合适的方法。