这个简单程序的输出是这是基础
。
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");
}
}
我的问题是,当我们使用这行
mainApp newObj = new returned();
时,我们实际上是否没有使用引用创建派生类的对象基类mainApp。那么,当我使用对象调用它的方法时,为什么不从派生类获取该方法呢?为什么我从基类获取方法。使用这一行,
mainApp newObj = new obliged();
,我们是在使用 mainApp 的引用,还是在使用 mainApp 的对象em>派生类。哪一个是正确的?
最佳答案
您获得基类方法的原因是 func
的基类版本已声明private
,并且Java不允许私有(private)方法被子类覆盖。这意味着,如果您扩展基类并且纯粹巧合地决定将私有(private)成员函数命名为与基类中的私有(private)成员函数相同的名称,则不会意外更改基类成员函数的行为。您确实正在使用 derived
类型的对象,但因为引用静态类型为 mainApp
,调用func
被解释为调用私有(private)方法 func
在mainApp
而不是公共(public)方法func
在derived
。更改代码读取
derived d = new derived();
d.func();
修复了这个问题,因为 d
的静态类型现在是derived
并调用 func
有不同的含义。
在JVM字节码级别,用于调用私有(private)成员函数的指令是invokespecial
而用于调用正常的、可重写的成员函数的指令是 invokevirtual
。两者的语义完全不同; invokespecial
开始查找当前类(或某些基类,例如构造函数),而 invokevirtual
在运行时查找与对象类型相对应的类。
关于java - 令人困惑的方法绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6782826/