代码如何在方法覆盖中流动

时间:2016-01-28 10:22:59

标签: java method-overriding

对于下面的代码,我得到了输出

In Base.foo()  
In Derived.bar()

代码:

class Base {
    public static void foo(Base bObj) {
        System.out.println("In Base.foo()");
        bObj.bar();
    }  
    public void bar() {
        System.out.println("In Base.bar()");
    }
}
class Derived extends Base {
    public static void foo(Base bObj) {
        System.out.println("In Derived.foo()");
        bObj.bar();
    }
    public void bar() {
        System.out.println("In Derived.bar()");
    }
}
class OverrideTest {
    public static void main(String []args) {
        Base bObj = new Derived();
        bObj.foo(bObj);
    }
}

代码如何流动?我如何得到如上所述的输出。我困惑一点,寻找解释。

2 个答案:

答案 0 :(得分:3)

不会覆盖静态方法,也没有虚拟调用。

Derived课程中,static foo方法隐藏其父类“static foo方法。

但是,在main方法中,您在引用类型foo上调用Base,因此Base#foo被调用(因此它会打印"In Base.foo()") 。

反过来,静态方法在传递的对象上调用bar IS-A Base,但恰好是Derived的实例。

由于bar是实例方法,并且在签名匹配的情况下覆盖,因此调用将解析为实例类型Derived,因此"In Derived.bar()"打印出来。

备注

  • 一个好的做法是在重写方法上使用@Override注释。 这将无法为您的foo方法编译,因为它是静态的,因此清楚地指出那里没有可能的重写。
  • 另一个好习惯(正如Jon Skeet所指出的)是避免在实例对象上调用static方法(即更喜欢明确的ClassName.staticMethod习语),因为这可能会导致混淆调用方法的范围。

答案 1 :(得分:0)

代码流程就像

Base bObj = new Derived();

在这里,您要创建类型为Base的bObj,运行时对象将是Derived类。

bObj.foo(BOBJ);

因为foo()是一个静态方法,静态绑定发生在编译时,因此它不会检查运行时对象类型。因此,当您声明一个Base类型对象时,Base中的方法将被执行。在该函数内部你用对象参数调用非静态方法bar()。在运行时传递的对象是你的Derived类实例,因此它将被调用。