我正在为考试做练习,发现一个样本问题使我完全迷失了。
对于以下代码,找到输出是什么:

class Moe {
    public void print(Moe p) {
        System.out.println("Moe 1\n");
    }
}
class Larry extends Moe {
    public void print(Moe p) {
        System.out.println("Larry 1\n");
    }
    public void print(Larry l) {
        System.out.println("Larry 2\n");
    }
}
class Curly extends Larry {
    public void print(Moe p) {
        System.out.println("Curly 1\n");
    }
    public void print(Larry l) {
        System.out.println("Curly 2\n");
    }
    public void print(Curly b) {
        System.out.println("Curly 3\n");
    }
}
public class Overloading_Final_Exam {
    public static void main (String [] args) {
        Larry stooge1 = new Curly();
        Moe stooge2 = new Larry();
        Moe stooge3 = new Curly();
        Curly stooge4 = new Curly();
        Larry stooge5 = new Larry();
        stooge1.print(new Moe());
        ((Curly)stooge1).print(new Larry());
        ((Larry)stooge2).print(new Moe());
        stooge2.print(new Curly());
        stooge3.print(new Curly());
        stooge3.print(new Moe());
        stooge3.print(new Larry());
        ((Curly)stooge3).print(new Larry());
        ((Curly)stooge3).print(new Curly());
        stooge4.print(new Curly());
        stooge4.print(new Moe());
        stooge4.print(new Larry());
        stooge5.print(new Curly());
        stooge5.print(new Larry());
        stooge5.print(new Moe());
    }
}


我想到了我的想法,但是当我运行Java时,我得到了完全不同的东西:

卷曲1
卷曲2
拉里1
拉里1
卷曲1
卷曲1
卷曲1
卷曲2
卷曲3
卷曲3
卷曲1
卷曲2
拉里2
拉里2
拉里1


前几个还可以,但是我真的不明白。
有人对此问题有很好的解释吗?

谢谢

最佳答案

我将从画一幅画开始...

Moe - print(Moe)
 |
Larry - print(Moe), print(Larry)
 |
Curly - print(Moe), print(Larry), print(Curly)


然后,我将跟踪变量:


拉里-stooge1->卷曲
萌-stooge2->拉里
萌-stooge3->卷曲
卷曲-stooge4->卷曲
拉里-stooge5->拉里
stooge1.print(new Moe())


stooge1-> Curly,因此称为Curly.print(Moe)

((Curly)stooge1).print(new Larry());


stooge1-> Curly,因此称为Curly.print(new Larry())

((Larry)stooge2).print(new Moe());


stooge2-> Larry叫Larry.print(new Moe());

stooge2.print(new Curly());
好的,这有点棘手(对不起,我之前在这里停过一个)


stooge2被声明为Moe。因此,当编译器正在查看要调用的内容时,它将调用print(Moe)方法。然后在运行时,它知道stooge2是Larry,因此它调用Larry.print(Moe)方法。



等等...

让我知道,如果这样做对您没有帮助。

(更新以澄清下一个)

因此,一般规则是:


编译器查看变量类型,以确定要调用的方法。
运行时将查看变量所指向的实际类,以决定从何处获取方法。


所以当你有:

Moe stooge2 = new Larry();
stooge2.print(new Moe());


编译器说:


可以将Larry分配给stooge2吗? (是的,因为Larry是Moe的子类)
Moe是否具有print(Moe)方法? (是)


运行时说:


我应该在此对象上调用print(Moe)方法... stooge2
stooge2指向拉里。
我将在Larry类中调用print(Moe)方法。


完成所有这些工作后,请尝试摆脱一些方法,然后看看这会如何改变。

09-05 08:31