令人困惑的方法绑定

Qua*_*fan 2 java oop polymorphism dispatch

这个简单程序的输出是This is base.

public class mainApp{
    private void func(){
      System.out.println("This is base"); 
    }

    public static void main(String[] args){
        mainApp newObj = new derived();
        newObj.func();
    }
}

class derived extends mainApp{
    public void func(){ 
      System.out.println("This is derived"); 
    }
}
Run Code Online (Sandbox Code Playgroud)
  • 我的问题是,当我们使用这一行时mainApp newObj = new derived();,我们实际上并没有使用基类mainApp的引用创建派生类的对象.所以,当我使用该对象调用它的方法时,为什么我不从派生类中获取方法?为什么我从基类中获取方法.

  • 使用这一行,我们是使用mainAppmainApp newObj = new derived();的引用还是我们正在使用派生类的对象.哪一个是正确的?

tem*_*def 8

您获得基类方法的原因func是声明了基类版本private,并且Java不允许子类重写私有方法.这意味着如果扩展基类并且纯粹巧合决定将私有成员函数命名为与基类​​中的私有成员函数相同的名称,则不会意外地更改基类的成员函数的行为.你确实是有类型的对象的工作derived,但由于基准是静态类型的mainApp,电话func被解释为调用私有方法funcmainApp,而不是公有方法funcderived.更改要读取的代码

derived d = new derived();
d.func();
Run Code Online (Sandbox Code Playgroud)

解决这个问题,因为d现在的静态类型derived和调用func具有不同的含义.

在JVM字节码级别,用于调用私有成员函数invokespecial的指令是用于调用普通,可覆盖成员函数的指令invokevirtual.两者的语义完全不同; invokespecial开始查看当前类(或类似构造函数的某些基类),而invokevirtual在运行时查找对应于对象类型的类.