繁体   English   中英

Java动态绑定

[英]Java dynamic binding

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

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)

然后,我将跟踪变量:

  • 拉里-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)方法。

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

实际上,这个问题并不像看起来那样简单,因为Java是静态的而且是动态绑定的。 您必须先了解每种方法的应用范围,然后才能理解从本练习中获得的所有结果。

TofuBeer提到的一般规则仅在动态绑定的情况下才是正确的。 在静态绑定中,决策仅在编译时做出。

您的示例混合了动态绑定(当方法被重写时)和静态绑定(当方法被重载时)。

请查看此问题以获取更多详细信息。

提示是在查看对象时忽略左侧的值。 而是在声明期间查看right的值,这是对象的实际值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM