运行时/编译时多态

时间:2010-03-19 06:03:03

标签: 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();

}

}

9 个答案:

答案 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

由于b1Base,而不是Child,对b1.subtract()的调用永远不会有效,因为b1没有名为{{subtract()的方法1}}。

答案 6 :(得分:0)

编译失败,因为BASE类没有减法方法。并且b1的类型为base。

答案 7 :(得分:0)

subtract()方法不是Base类接口的一部分,这就是它失败的原因。

答案 8 :(得分:-1)

Java是严格的静态类型语言。父类不能指向子类方法。在编译时,Java编译器使用闭包原理并查看Base类中是否有减法方法,因为在这种情况下没有减法方法会导致编译时错误。