Java动态绑定
我正在练习考试,发现了一个让我完全迷路的样例问题。 对于以下代码,请查找输出内容:Java动态绑定,java,binding,overloading,method-dispatch,Java,Binding,Overloading,Method Dispatch,我正在练习考试,发现了一个让我完全迷路的样例问题。 对于以下代码,请查找输出内容: 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 voi
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
卷曲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)
然后我会跟踪变量:
- 拉里-斯托吉1->Curly
- Moe-stooge2->Larry
- Moe-stooge3->Curly
- 卷曲-弯腰4->卷曲
- 拉里-斯托吉5->拉里
stooge1.打印(新Moe())
- stooge1->Curly so调用Curly.print(Moe)
((卷曲的)凳子1.print(新拉里())代码>
- stooge1->Curly so调用Curly.print(new Larry())
((Larry)stooge2).print(新Moe())代码>
- stooge2->Larry这么叫Larry.print(新Moe())李>
stooge2.print(新卷发())代码>
好的,这是它变得有点棘手的地方(很抱歉我在这里之前停止了一个)- stooge2被宣布为教育部。因此,当编译器查看调用什么时,它将调用print(Moe)方法。然后在运行时它知道stooge2是Larry,所以它调用Larry.print(Moe)方法
- 编译器查看变量类型以决定调用哪个方法
- 运行时查看变量所指向的实际类,以决定从何处获取方法
Moe stooge2 = new Larry();
stooge2.print(new Moe());
编者说:
- 拉里能被分配到stooge2吗?(是,因为Larry是Moe的一个子类)
- Moe是否有打印(Moe)方法?(是的)
- 我应该调用这个对象的print(Moe)方法。。。走狗2
- stooge2指的是拉里
- 我将在Larry类中调用print(Moe)方法
一旦你解决了所有这些问题,试着去掉一些方法,看看它们是如何改变的。实际上,这个问题并不像看上去那么简单,因为Java是静态和动态绑定的。在理解本练习的所有结果之前,您必须了解每个应用的位置 TofuBeer提到的一般规则仅在动态绑定情况下正确。在静态绑定中,决策只在编译时做出 您的示例混合了动态绑定(重写方法时)和静态绑定(重载方法时)
查看更多详细信息。前3个是直截了当的。如果你能继续下一个3,那会有帮助的。谢谢上面的更改应该会有所帮助。@TofuBeer-不完全正确。在纯动态绑定的情况下,stooge2.print(新的Curly())将打印“Larry 2”而不是“Larry 1”,因为Curly扩展了Larry。(实际上,stooge2.print(new Larry())是一个更好的例子,因为它也会打印“Larry 1”而不是“Larry 2”。这会使错误更加明显。重载方法是静态绑定的,这就是为什么不调用它的原因。因为在这种情况下,该方法是动态绑定的,这只发生在被重写的方法中。是的,stooge2.print(new Larry())将与stooge2.print(new Moe())相同,因为Moe没有打印(Larry)在Java语言中,stooge2.print(new Larry())无法调用Larry.print(Larry)方法。