Java:对象的初始化序列

INl*_*ELL 5 java oop inheritance

有一个代码作为初级Java开发人员的任务给出.我在五年内使用Java,这段代码让我很困惑:

public class Main {

    String variable;

    public static void main(String[] args) {
        System.out.println("Hello World!");
        B b = new B();
    }

    public Main(){
        printVariable();
    }

    protected void printVariable(){
        variable = "variable is initialized in Main Class";
    }
}

public class B extends Main {

    String variable = null;

    public B(){
        System.out.println("variable value = " + variable);
    }

    protected void printVariable(){
        variable = "variable is initialized in B Class";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出将是:

Hello World!
variable value = null
Run Code Online (Sandbox Code Playgroud)

但如果我们改变String variable = null;,String variable;我们会:

Hello World!
variable value = variable is initialized in B Class
Run Code Online (Sandbox Code Playgroud)

第二个输出对我来说更清楚.所以,据我所知,Java中的inizialisation序列如下:

  • 当我们来到这个根父类时,我们转到类层次结构的根(对于Java,它总是Object类):
    • 所有静态数据字段都已初始化;
    • 执行所有静态字段初始化程序和静态初始化程序段;
    • 初始化所有非静态数据字段;
    • 执行所有非静态字段初始化器和非静态初始化块;
    • 执行默认构造函数;
  • 然后我们重复底层子类的过程.

还有post描述this了超类的上下文中关键字的行为- 从基类方法调用基类重写函数

根据上面给出的规则,我假设有这样的序列:

  1. 我们将创建一个新的类实例B;
  2. 我们去参加课程Main;
  3. 初始化main.variable为null;
  4. 然后我们转到class的默认构造函数Main;
  5. 构造函数b.printVariable()在类中调用方法Main; (为什么不打电话main.printvariable?我们this这里没有关键词.)
  6. 字段b.variable" 变量在B类中初始化 "
  7. 现在我们回到课堂上B;
  8. 我们应该b.variable用null值初始化字段,对吗?
  9. B执行的类的默认构造函数

请,有人可以完整和完整地解释这种继承i​​nizialisation序列是如何工作的.为什么改变String variable = null;String variable;导致另一个输出.

Joh*_*red 9

顺序是:

  1. 主要 - >"你好"
  2. 主要 - >新B()
  3. B() - > Main() - > b.printVariable() - >设置变量
  4. 回到初始化B,所以变量= null.

所以基本上,超级对象Main()是在B类的任何初始化事件之前构造的.这意味着变量= null会在以后发生.这是有道理的,否则B可以打破Main的初始化.

约书亚布洛赫在他有效的java书中介绍了很多关于如何做正确的危险继承的好理由,我会推荐它.