不清楚动态绑定

cod*_*ato 16 java

我不了解动态绑定和适当覆盖的概念:

这是一些代码:

class Cake {
    public void taste (Cake c) {
        System.out.println("In taste of Cake class");
    }
}

class ChocolateCake extends Cake {
    public void taste(Cake c) {
        System.out.println("In taste (Cake version) of ChocolateCake class");
    }
    public void taste(ChocolateCake cc) {
        System.out.println("In taste (ChocolateCake version) of ChocolateCake class");
    }
}


public static void main(String[] args)
{
    ChocolateCake cc = new ChocolateCake();
    Cake c = new ChocolateCake();
    Cake c1 = new Cake();
    Cake c2 = new ChocolateCake();

    c1.taste(cc);
    c1.taste(c);

    c2.taste(cc);
    c2.taste(c);
}
Run Code Online (Sandbox Code Playgroud)

我期望:

In taste of Cake class
In taste of Cake class
In taste (ChocolateCake version) of ChocolateCake class" <----
In taste (Cake version) of ChocolateCake class
Run Code Online (Sandbox Code Playgroud)

实际:

In taste of Cake class
In taste of Cake class
In taste (Cake version) of ChocolateCake class <----
In taste (Cake version) of ChocolateCake class
Run Code Online (Sandbox Code Playgroud)

如果对象的类型为ChocolateCake,并且我将cc称为ChocolateCake,那么编译器如何显示它正在将Cake作为参数?

Swe*_*per 9

这是因为在这种情况下,Java使用静态绑定和动态绑定来选择要调用的方法。

问题所在的行是这样,对吗?

c2.taste(cc);
Run Code Online (Sandbox Code Playgroud)

编译器首先选择要调用的方法(静态绑定)。由于c2是编译时类型的Cake,因此编译器仅看到该taste(Cake)方法。因此它说“打电话taste(Cake)”。

现在,在运行时,运行时需要taste(Cake)根据的运行时类型选择要调用的实现c2。这是动态绑定。它会选择一个Cake吗?还是其中之一ChocolateCake?由于c2是运行时类型ChocolateCake,因此将调用taste(Cake)in 的实现ChocolateCake。

如您所见,您taste(ChocolateCake)甚至没有提到您以为将被称为-的方法!这是因为这是方法的另一种重载taste,并且因为它在ChocolateCake类中,编译器看不到。编译器为什么看不到?因为c2是编译时类型的Cake。

简而言之,编译器决定哪个重载,运行时决定哪个实现。

回应您的陈述:

如果对象是ChocolateCake类型...

只有您知道对象的类型ChocolateCake。编译器没有。它只知道c2类型,Cake因为它的声明就是这样。


Ful*_*Guy 8

由于c2变量的引用类型是具有类型参数Cake的taste方法,因此Cake将被调用。

这是因为Cake类型没有taste采用ChocolateCake实例的方法,因此您不能从Cake类型引用变量中调用该方法。

现在,第二,在Java中,由于运行时多态性的机制,正在调用的重写taste方法,ChocolateCake而不是在父Cake类中声明的版本。这是由于实际上在运行时Cake将检查引用所指向的对象,并taste会调用该特定实例的版本。

因此,由于这两种效果的结合,您可以看到输出。

如果将的引用类型更改为c2,ChocolateCake则会看到输出为:

In taste (ChocolateCake version) of ChocolateCake class 
Run Code Online (Sandbox Code Playgroud)

当您调用时c2.taste(cc);,由于现在编译器和运行时都同意taste(ChocolateCake cc)特别调用该方法。