Java静态和动态绑定,重载 [英] Java Static and Dynamic Binding, Overloading

查看:183
本文介绍了Java静态和动态绑定,重载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在为测试做练习,我遇到了有关重载以及静态和动态绑定的练习.询问以下代码的输出:

I am practicing for a test and I came across this exercise about overloading and static and dynamic binding. The output of the following code is asked:

class Moe {
    public void print(Moe p) {
        System.out.println("Moe 1");
    }
}

class Larry extends Moe {
    public void print(Moe p) {
        System.out.println("Larry 1");
    }
    public void print(Larry l) {
        System.out.println("Larry 2");
    }
}

class Curly extends Larry {
    public void print(Moe p) {
        System.out.println("Curly 1");
    }
    public void print(Larry l) {
        System.out.println("Curly 2");
    }
    public void print(Curly b) {
        System.out.println("Curly 3");
    }
}

class Overloading {
    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());
        stooge1.print(new Curly());
        stooge1.print(new Larry());
        stooge2.print(new Curly());
        stooge3.print(new Curly());
        stooge3.print(new Larry());
        stooge5.print(new Curly());
    }
}

认为我得到了第一个,但在其他方面我完全迷失了.这就是我解决第一个问题的方法:

I think I get the first one but on the others I am completely lost. This is how I solved the first one:

在运行时stooge1的类型为Curly,因此我们将调用Curly的打印方法.因为我们传递了类型为Moe的对象进行打印,所以参数类型为Moe的相应打印方法在Curly中运行.此方法的输出是正确的答案Curly 1.

at runtime the type of stooge1 is Curly, so we're calling the print method of Curly. Because we pass an object of type Moe to print, the corresponding print method with argument type Moe is run in Curly. The output of this method is Curly 1, the correct answer.

但是,当我将这种技术应用于以下几行时,我得到的答案是错误的.有人可以解释一下这个概念在Java中是如何工作的吗?

However, when I apply this technique to the following lines I end up with the wrong answers. Can someone explain me how exactly this concept works in Java?

代码的正确输出是:

Curly 1
Curly 2
Curly 2
Larry 1
Curly 1
Curly 1
Larry 2

推荐答案

静态绑定在编译时发生,动态绑定在运行时发生.

Static binding happens at compilation time and dynamic binding at runtime.

  • 静态绑定负责选择应执行的方法的签名(名称和参数类型).它使用

  • Static binding is responsible for selecting signature (name and argument types) of method which should be executed. It uses

    方法的
  • 名称
  • 具有参数的变量类型(编译器不假定运行时实际的对象变量将保留,他选择了能够处理所有可能情况的签名).
  • name of method
  • type of variables holding arguments (compiler doesn't assume what actual object variable will hold at runtime, he picks signature which will be able to handle all of possible cases).

编译器从调用方法的变量类型中选择签名 ,因此Object o = "abc";不允许允许您调用o.substring(1,2);,因为编译器将无法在Object类(调用substring方法的o变量的类型)中找到substring(int, int)签名.

Compiler selects signature from variable type on which method is invoked, so Object o = "abc"; will not allow you to invoke o.substring(1,2); because compiler will not be able to find substring(int, int) signature in Object class (which is type of o variable on which substring method was invoked).

动态绑定负责查找和调用在编译时通过静态绑定选择的方法的代码 .它将尝试查找变量持有的实际实例类型的方法的代码.换句话说,如果您具有Animal a = new Cat(); a.makeSound();,则可以期望得到结果"Mew",因为在运行时JVM将从Cat类开始搜索并调用makeSound的代码.如果该类中未提供实现,则JVM将在祖先中搜索它,直到找到继承它的一个.

Dynamic binding is responsible for finding and invoking code of method selected by static binding at compilation time. It will try to find code of method in type of actual instance held by variable. In other words if you have Animal a = new Cat(); a.makeSound(); you can expect to get as result "Mew" because at runtime JVM will search and invoke code of makeSound starting from Cat class. If implementation will not be provided in that class JVM will search for it in ancestor(s) until it finds one from which it was inherited.

在您的示例中,我对类和变量进行了重命名,以期使其更具可读性:

I renamed classes and variables in your example a little to hopefully make it more readable:

class A {
    public void print(A a) {
        System.out.println("A.print(A)");
    }
}

class B extends A {
    public void print(A a) {
        System.out.println("B.print(A)");
    }
    public void print(B b) {
        System.out.println("B.print(B)");
    }
}

class C extends B {
    public void print(A a) {
        System.out.println("C.print(A)");
    }
    public void print(B b) {
        System.out.println("C.print(B)");
    }
    public void print(C c) {
        System.out.println("C.print(C)");
    }
}

class OverloadingDemo {
    public static void main (String [] args) {
        A ab = new B();
        A ac = new C();
        B bb = new B();
        B bc = new C();

        bc.print(new A());
        bc.print(new C());
        bc.print(new B());
        ab.print(new C());
        ac.print(new C());
        ac.print(new B());
        bb.print(new C());
    }
}

(变量命名->类型为X且保存类型为Y的实例的变量被命名为xy).

(variable naming -> variable of type X holding instance of type Y is named xy).

所以,当我们执行

bc.print(new A());

  • 静态绑定将尝试找到最佳的print方法签名在类B 中可用,该签名可以处理类型为A的实例.在这种情况下,它将为print(A).
  • 之后,动态绑定将在类C中搜索此方法的 code (因为这是bc变量持有的实例的类型),这意味着我们将看到C.print(A)./li>

    • static binding will try to find best print method signature available in class B which can handle instance of type A. In this case it will be print(A).
    • after that dynamic binding will search for code of this method in class C (since this is type of instance held by bc variable) which means we will see C.print(A).
    • 对于bc.print(new C());

      • 静态绑定将尝试为B类中可用的C参数找到最佳的print方法,对于Cprint(B)(因为那里没有print(C)并且B是最接近的超类型) .
      • 因此,现在动态绑定知道要在C类中查找哪种方法(因为这是bc所拥有的实例).
      • static binding will try to find best print method for C argument available in B class, which for C is print(B) (since there is no print(C) there and B is closest supertype).
      • So now dynamic binding knows which method to look for in C class (since this is instance which bc holds).

      因此它将调用C.print(B).

      这篇关于Java静态和动态绑定,重载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆