【问题标题】:Please explain this behaviour in java请在java中解释这种行为
【发布时间】:2015-11-20 14:01:45
【问题描述】:
class abc extends TestStart{
     static{
         System.out.println("c");
     }
     {
         System.out.println("f");
     }
     public abc(){
         System.out.println("d");
     }
}

public class TestStart {
     static {
         System.out.println("A");
     }
     {
         System.out.println("z");
     }
     public TestStart(){
         System.out.println("b");
     }

     public static void main(String[] args) {

         TestStart x = new abc();
         TestStart y = new TestStart();             
     }
}

输出-----------> 一种 C z b F d z b

我认为这个的输出行为---->>>>> TestStart x = new abc(); --------应该是:-

  1. 将运行两个类的第一个静态块
  2. 然后由于 new abc() 将调用子类的 init 块。但是这里调用父类的 init
  3. 然后从 new abc() 调用 super(),从而调用父类构造函数。
  4. 在父类构造函数之前,会执行父类的init块。
  5. 然后parnet类的构造函数将执行
  6. 然后子类的构造函数将执行。

我应该得到以下输出: 一种 C F z b d z b

这种行为很大程度上源于父类和子类中没有init块。 请解释我提到的输出。

【问题讨论】:

  • "然后由于 new abc() 将调用子类的 init 块" 这听起来像是从屋顶开始建造房子......一个初始化的父实例是子类的基础,所以需要先构建。

标签: java inheritance constructor initialization instance


【解决方案1】:

您有:A 987654322 z 987654324 f 987654326 z 987654328 @同时你的预期:A 987654330 f 987654332 b 987654334@zb

所以,您是说您希望 f 在 z b 之前发生。

所以,你本质上说的是你所期望的:

  • 最派生类的实例初始化器 (f)

在之前调用

  • 基类的实例初始化器 (z) 和
  • 基类的构造函数(b)。

嗯,事情根本不是这样发生的。基类的所有实例初始化必须在派生类的实例初始化开始之前完成,否则派生类将能够访问基类未初始化的成员。

所有静态初始化的东西(A,c)都是在问题中抛出的红鲱鱼来迷惑我们。

【讨论】:

    【解决方案2】:

    在所有类中初始化静态块和变量后,都会运行父类的初始化程序。在父构造函数之后,然后是子构造函数中的子构造函数。 那是因为您可以在子初始化程序中使用一些父字段,因此必须先初始化它们。

    【讨论】:

    • 但是调用父类构造函数背后的原因是子类构造函数内部的super()。这就是为什么父类构造函数首先运行。并且在调用构造函数init块之前应该运行。我没有得到先生
    • 初始化器在 super() 之后运行
    【解决方案3】:

    首先,一些命名:

     public class TestStart {
       static { // static initializer
         System.out.println("A");
       }
       { // instance initializer
         System.out.println("z");
       }
       public TestStart() { // constructor
         System.out.println("b");
       }
     }
    

    首先调用静态初始化器是对的,但唯一的保证是在任何上下文中使用该类之前调用​​类静态初始化器。

    对于实例初始化器和构造器,调用顺序如下,从第一次调用到最后一次调用:

    Parent initializer, Parent Constructor, Your Initializer, Your Constructor
    

    如果您使用 this() 从同一类调用其他构造函数,则在您的类中的所有构造函数调用之前调用一次初始化程序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-16
      • 2011-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-07
      相关资源
      最近更新 更多