2

这个简单程序的输出是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"); 
    }
}
  • 我的问题是,当我们使用这一行时mainApp newObj = new derived();,我们实际上并没有使用基类mainApp的引用创建派生类的对象。那么,当我使用对象调用它的方法时,为什么不从派生类中获取方法呢?为什么我从基类中获取方法。

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

4

2 回答 2

8

您获得基类方法的原因func是声明了基类版本private,并且 Java 不允许私有方法被子类覆盖。这意味着,如果您扩展一个基类并且出于巧合决定将私有成员函数命名为与基类​​中的私有成员函数相同的名称,您不会意外更改基类成员函数的行为。您确实在使用类型的对象derived,但由于引用静态类型为 a mainApp,因此调用func被解释为调用 in 中的私有方法而不是 in 中的公共方法。更改要读取的代码funcmainAppfuncderived

derived d = new derived();
d.func();

解决了这个问题,因为dis now的静态类型derived和对的调用func具有不同的含义。

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

于 2011-07-21T21:12:18.243 回答
0

你正在与derived班级一起工作。对该对象的引用是mainApp. 这意味着其他人将其视为一个mainApp,但它被实现为派生类。

于 2011-07-21T21:11:53.180 回答