本Java代码中构造函数的顺序是什么?

这是代码,我定义了两个名为Father和Son的类,并在main函数中创建它们:

public class Test { public static void main(String[] args) { Father father = new Son(); } } class Father { private String name = "father"; public Father() { who(); tell(name); } public void who() { System.out.println("this is father"); } public void tell(String name) { System.out.println("this is " + name); } } class Son extends Father { private String name = "son"; public Son() { who(); tell(name); } public void who() { System.out.println("this is son"); } public void tell(String name) { System.out.println("this is " + name); } } 

我得到了这样的输出:

 this is son this is father this is son this is son 

但我无法理解这是怎么发生的? 谁能告诉我为什么?

  1. 让我们从Son的构造函数开始。

     public Son() { super(); // implied who(); tell(name); } 
  2. 父亲的构造函数被调用。

     public Father() { who(); tell(name); } 
  3. 因为who()Son所覆盖,所以将调用Son的版本,打印“这是儿子”。

  4. tell()也被覆盖,但传入的值是Father.name ,打印“this is father”。

  5. 最后,在Son的构造函数中调用who()tell(name)将分别打印出“this is son”和“this is son”。

以下是所谓的:

 new Son() => Son._init => first every constructor calls super() Father._init Object._init who() => is overridden, so prints "son" tell(name) => name is private, so cannot be overridden => "father" who() => "son" tell(name) => "son" 

要吸取的教训:

  • 私有字段和方法是私有的。 不能被覆盖。
  • 不要从可以被覆盖的构造函数中调用方法。 这可以调用半初始化类状态的方法(尽管不会发生在你的情况下)。

创建Son实例时,将调用父类的构造函数(即Father() ); 这里调用了who()方法,但它是你在Son声明的重写版本,所以这里是你的第一行(其中String在方法中被硬编码)。

第二行来自于Father()tell(name) ,其中tell()被覆盖但是name == "father"因为调用来自Father的构造函数,而name是类Fatherprivate字段。

Control返回Son()构造函数,最后两行直接来自Son类构造函数。

Son()之前调用Father() Son() 。 隐式调用超类默认构造函数,我们这里不需要super()语句。

Father()的构造函数中的who()调用重写方法。

上面的代码特别是Bad Style(TM)。 😉

会发生什么:没有父实例,只有Son实例。 (然而,它与父亲兼容。)

Son构造函数调用父构造函数。 后者调用重写的(!)方法,因此永远不会调用Father.who和Father.tell! 在子构造函数完成之前(!)调用重写的方法。

我的建议:

  1. 如果在构造函数中调用方法,请将其设为final。 或者让全class决赛。 或者至少将被调用的方法设为私有。
  2. 永远不要覆盖构造函数中调用的方法。
  3. 如果您不得不违反上述建议,请写下有关您为什么这样做以及您希望发生什么的广泛评论。 编写unit testing以确保您的假设有效。