关于Java中动态转换的大学任务

时间:2018-01-05 14:29:10

标签: java dynamic interface casting

在大学时,我们获得了一个Java程序,并负责了解输出是如何形成的。该计划如下:

interface A {
    public void f(A x);
}

interface AA extends A {
    public void f(B x);
}

class B implements A {
    public void f (A x) {System.out.println("1");}
    public void f (B x) {System.out.println("2");}
    public void f (C x) {System.out.println("3");}
}

class C implements A,AA {
    public void f(A x) {System.out.println("4");}
    public void f(B x) {System.out.println("5");}
    public void f(C x) {System.out.println("6");}
}

public class Task7 {
    public static void main(String[] args) {
        B b = new B();  C c = new C();
        A ac = c;       A ab = b;
        AA aac = c;

        b.f(b);         c.f(c);
        ac.f(b);        ab.f(b);
        aac.f(b);       aac.f(c);
    }
}

输出为“264154”。我真的不明白最后4个数字是如何解释的。有人可以帮忙吗?

编辑:要进一步解释我的问题: 'b.f(b)'显然会打印出2,因为你给B对象提供B引用,'c.f(c)'将出于同样的原因打印6。

'ab.f(b)'将调用'bf(b)'因为它的动态类型是B.现在,我不明白为什么参数'b',之前已被同一类看到'B',现在被理解为'A',因此“1”被打印而不是“2”。对于其他方法调用也是如此,我只是不明白为什么同一个底层对象的相同参数被不同地解释

2 个答案:

答案 0 :(得分:3)

多态性仅应用于.左侧的对象。无论传递的值如何,编译器都会确定在编译时调用哪个方法签名。

e.g。

B b = new B();
b.f((A) null);
b.f((B) null);
b.f((C) null);

123打印为仅在编译时已知的引用类型。

同样,在调用静态方法时,如果使用引用,则只引用类型。

Thread t = null;
t.yield(); // call Thread.yield() so no NullPointerException.
  

我只是不明白为什么同一个基础对象的相同论点被不同地解释

方法签名是在编译时根据引用类型确定的。

另一种看待它的方法是多态只适用于重写方法,而不是重载方法。

答案 1 :(得分:1)

首先,你必须真正了解多态性。

我不打算解释为什么打印出前两个值,但我觉得有趣的是知道为什么其他值有这些输出。

因此,让我们检查第三个:ac.f(b); ac是A:A ac = c;的实例,c是C的实例:C c = new C();。因此,A ac = new C();表示ac只能使用C类中的函数,并且在这些函数中它只能调用在A接口中编写的函数:public void f(A x) {System.out.println("4");}(编译器不关心类型参数部分中的对象)

其他示例:ab.f(b);这是您在输出中获得的第四个数字。 ab是A的实例:A ab = b,b是B的实例:B b = new B();。因此,A ab = new B();。这意味着ab可以调用A中B 内声明的所有函数,这就是为什么:public void f (A x) {System.out.println("1");}。(请记住它们必须在两个部分中声明,而不是仅在一个部分中声明)。