在下面的代码中,为什么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();
}
}
答案 0 :(得分:7)
我认为,从标题来看,代码实际上是b2.subtract()
。跟着这个:
虽然b2目前是Child的一个实例,但很容易看出在你的代码中它总是一个Child的实例,Java是静态类型的,所以不能让你使用实际的方法class,只是声明的类。
考虑这个例子:
Base b2 = Math.random() > 0.5 ? new Base() : new Child();
b2.subtract();
现在不可能在编译时告诉b2实际上是什么实例,所以你显然不可能调用Child中的任何方法(因为b2可能只是一个普通的Base!)。对于像你的例子这样的情况会出现异常是没有意义的,因为它会导致混淆 lot ,这些情况可以很容易地纠正到原样正常工作(通过将声明的类型更改为Child not Base)。
答案 1 :(得分:1)
JVM中没有任何事情发生,因为代码无法编译。编译器无法解析方法b1.subtract()
,因为Base没有此类成员。
答案 2 :(得分:1)
该类无法编译!假设您想检查使用子类实例化的基类对象是否有效,答案是肯定的。
Base b1 = new Base();
Base b2 = new Child();
Child b3 = new Child();
b1.add();
((Child) b2).subtract(); // ?????????**
b2.add();
b3.subtract();
这将起作用,它给出的输出如下。
Base ADD
Child Subtract
Child ADD
Child Subtract
这就是所谓的运行时多态性。
答案 3 :(得分:0)
b1
变量的类型为Base
。该类没有subtract()
方法,因此无法编译。
答案 4 :(得分:0)
'因为Base没有减法。
b2和b3已减去'因为它们被定义为Child。
[编辑:]不,等等,b2没有减法,即使它是用新的Child()定义的,它仍然被声明为Base。
答案 5 :(得分:0)
对b1.subtract()
的调用可以分解为正在使用的类。
b1
- > Base
subtract()
- > Child
由于b1
是Base
,而不是Child
,对b1.subtract()
的调用永远不会有效,因为b1
没有名为{{subtract()
的方法1}}。
答案 6 :(得分:0)
编译失败,因为BASE类没有减法方法。并且b1的类型为base。
答案 7 :(得分:0)
subtract()方法不是Base类接口的一部分,这就是它失败的原因。
答案 8 :(得分:-1)
Java是严格的静态类型语言。父类不能指向子类方法。在编译时,Java编译器使用闭包原理并查看Base类中是否有减法方法,因为在这种情况下没有减法方法会导致编译时错误。