从构造函数调用重写的方法

时间:2011-12-09 18:39:23

标签: java constructor

在以下示例中:

class Base {    
    int  x=10;  

    Base() {    
      show();
    }  

    void show() {   
        System.out.print ("Base Show " +x + "  ");
    }  
}  

class Child extends Base {   
    int x=20;  

    Child() {
        show();
    }  

    void show() {    
        System.out.print("Child Show " + x +"  ") ; 
    }  

    public static void main( String s[ ] ) {   
        Base obj = new Child();   
    }  
} 
  • 为什么输出如下所示
Child Show 0  Child Show 20
  • 我认为构造函数只有在超级构造函数完成后才能访问实例成员。

我认为这里发生的是超级构造函数调用子的show()方法,因为这个方法在Child中被重写。因为它已被重写但为什么x 0的值以及为什么它可以在超级构造函数完成之前访问此方法?

4 个答案:

答案 0 :(得分:11)

  

我认为这里发生的事情是超级构造函数调用了孩子的show()方法,因为这个方法在Child中被覆盖了。

这是正确的

  

但为什么x 0的值

因为它尚未初始化(儿童的x)

  

为什么它可以在超级构造函数完成之前访问此方法?

这就是为什么在构造函数中你永远不应该调用一个可以被覆盖的方法(非最终公共和受保护)。

编辑:

这里奇怪的是,一切都有默认/包私有的可见性。这可能会产生一些奇怪的效果。请参阅:http://www.cooljeff.co.uk/2009/05/03/the-subtleties-of-overriding-package-private-methods/

我建议尽可能避免使用默认可见性覆盖方法(您可以通过将它们声明为最终来防止这种情况)。

答案 1 :(得分:6)

您可以从构造函数中调用overriden方法,但是错误并且不应该。您说明了这个错误的原因:派生类没有机会进行初始化,因此将使用未初始化的字段 - 在您的示例中,int x的默认值为0,即为什么要打印0

答案 2 :(得分:2)

构造函数链接它有意义解释究竟是什么。子类构造函数方法的第一个任务是调用其超类的构造函数方法。这确保了子类对象的创建始于继承链中它上面的类的初始化。

http://java.about.com/b/2009/02/07/java-term-of-the-week-constructor-chaining.htm

http://javahours.blogspot.com/2008/12/constructor-chain.html

答案 3 :(得分:1)

调用{p> Child覆盖show方法,因为这是Java规范所要求的。这是一个great discussion of why you should not do it。 x的值为零,因为Child尚未完成初始化。