运行时/编译时多态

Jav*_*ser 2 java

在下面的代码中,为什么b1.subtract()失败.请解释一下原因,即调用该方法时JVM中会发生什么.

class Base {

public void add() {
System.out.println("Base ADD");
}

}

class Child extends Base {

public void add(){
System.out.println("Child ADD");
}

public void subtract() {
System.out.println("Child Subtract");
}

}

class MainClass {

public static void main(String args[]) {

Base b1 = new Base();
Base b2 = new Child();

Child b3 = new Child();

b1.add();

b2.subtract(); // ?????????**previously it was b1.subtract and its wrong 

b2.add();
b3.subtract();

}

}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 7

我认为,从标题来看,代码实际上是指的b2.subtract().跟着那个:

虽然b2目前是Child的一个实例,但很容易看出在你的代码中它总是一个Child的实例,Java是静态类型的,所以不能让你使用实际类的方法,只是声明的类.

考虑这个例子:

Base b2 = Math.random() > 0.5 ? new Base() : new Child();
b2.subtract();
Run Code Online (Sandbox Code Playgroud)

现在在编译时不可能告诉b2实际上是什么实例,所以你显然不可能调用Child中的任何方法(因为b2可能只是一个普通的Base!).对于像你的例子这样的例子来说,这是一个例外是没有意义的,因为它会引起很多混乱,这些案例可以很容易地纠正到原样正常工作(通过将声明的类型更改为Child)不是基地).

  • 我只想补充一点,继承点是如果你声明"Base b1"然后再说"b1.add",你是执行Base.add还是Child.add取决于对象的运行时类型.但正如Chris解释的那样,你只能调用声明类中的函数,因为这就是编译器可以确定存在的全部内容. (4认同)