我正在练习考试,发现了一个让我完全迷失的样本问题.对于以下代码,找到输出的内容:
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时,我得到了完全不同的东西:
Curly 1 Curly 2 Larry 1 Larry 1 Curly 1 Curly 1 Curly 1 Curly 2 Curly 3 Curly 3 Curly 1 Curly 2 Larry 2 Larry 2 Larry 1
前几个是好的,但后来我真的不明白.有人对这个问题有很好的解释吗?
谢谢
我会先画一张照片......
Moe - print(Moe) | Larry - print(Moe), print(Larry) | Curly - print(Moe), print(Larry), print(Curly)
然后我会跟踪变量:
Larry - stooge1 - > Curly
Moe - stooge2 - >拉里
Moe - stooge3 - >卷曲
Curly - stooge4 - > Curly
Larry - stooge5 - > Larry
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());
编译器说:
拉里可以被分配到stooge2吗?(是的,因为Larry是Moe的子类)
Moe有印刷(Moe)方法吗?(是)
运行时说:
我应该在这个对象上调用print(Moe)方法... stooge2
stooge2指向拉里.
我将在Larry课程中调用print(Moe)方法.
一旦你完成了所有这些,尝试摆脱一些方法,看看它是如何改变的.