简体   繁体   English

Java:对象的初始化序列

[英]Java: initialization sequence of object

There is a code which is given as a task for a junior Java developers. 有一个代码作为初级Java开发人员的任务给出。 I use Java during five years and this piece of code completely confusing me: 我在五年内使用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";
    }
}

The output will be: 输出将是:

Hello World!
variable value = null

But if we change String variable = null; 但是如果我们改变String variable = null; to String variable; String variable; we will have: 我们将有:

Hello World!
variable value = variable is initialized in B Class

The second output is more clear for me. 第二个输出对我来说更清楚。 So, as far as I know the sequence of inizialisation in Java like this: 所以,据我所知,Java中的inizialisation序列如下:

  • We go to the root of the class hierarchy (for Java it is always Object class), when we come to this root parent class: 当我们来到这个根父类时,我们转到类层次结构的根(对于Java,它总是Object类):
    • All static data fields are initialized; 所有静态数据字段都已初始化;
    • All static field initializers and static initialization blocks are executed; 执行所有静态字段初始化程序和静态初始化程序段;
    • All non-static data fields are initialized; 初始化所有非静态数据字段;
    • All non-static field initializers and non-static initialization blocks are executed; 执行所有非静态字段初始化器和非静态初始化块;
    • The default constructor is executed; 执行默认构造函数;
  • Then we repeat the procedure for the underlying child class. 然后我们重复底层子类的过程。

Also there is post which describes the behavior of the this keyword in context of a superclass - Calling base class overridden function from base class method 还有post描述了this关键字在超类的上下文中的行为 - 从基类方法调用基类重写函数

Based on the rules given above, I assume to have sequence like this: 根据上面给出的规则,我假设有这样的序列:

  1. We are going to create a new instance of class B ; 我们将创建一个B类的新实例;
  2. We go to the part class Main ; 我们去零件类Main ;
  3. Initialize main.variable with null; 用null初始化main.variable ;
  4. Then we move to the default constructor of class Main ; 然后我们转到Main类的默认构造函数;
  5. Constructor calls method b.printVariable() in class Main ; 构造函数在Main类中调用方法b.printVariable() ; (Why doesn't it call main.printvariable ? We don't have this key word here.) (为什么不调用main.printvariable ?我们这里没有this关键词。)
  6. The field b.variable " variable is initialized in B Class " 字段b.variable变量在B类中初始化
  7. Now we come back to the class B ; 现在我们回到B级;
  8. We should initialize field b.variable with null value, am I right?; 我们应该用空值初始化字段b.variable ,我是对的吗?
  9. The default constructor of class B executed 执行了B类的默认构造函数

Please, can someone give a complete and full explanation of how this inheritance inizialisation sequence works. 请,有人可以完整和完整地解释这种继承i​​nizialisation序列是如何工作的。 And why changing String variable = null; 为什么更改String variable = null; to String variable; String variable; leads to another output. 导致另一个输出。

The sequence is: 顺序是:

  1. Main -> "Hello" 主要 - >“你好”
  2. Main -> new B() 主要 - >新B()
  3. B() -> Main() -> b.printVariable() -> sets the variable B() - > Main() - > b.printVariable() - >设置变量
  4. Back to initialising B, so variable=null occurs. 回到初始化B,所以变量= null。

So basically, the super object Main() is constructed before any intialisation events of class B. Which means variable=null occurs later. 所以基本上,超级对象Main()是在B类的任何初始化事件之前构造的。这意味着变量= null会在以后发生。 This makes sense as otherwise B could break the initialisation of Main. 这是有道理的,否则B可以打破Main的初始化。

Joshua Bloch covers a lot of good ground in his effective java book about how dangerous inheritance is to get right, I would recommend it. 约书亚布洛赫在他有效的java书中介绍了很多关于如何做正确的危险继承的好理由,我会推荐它。

First, you need to understand, what happens when you write variable = null; 首先,您需要了解,当您编写variable = null;时会发生什么variable = null; . When is that code executed. 该代码何时执行。 This basically determines the output. 这基本上决定了输出。

Before I begin, I should also mention that when you create an object of class B , the printVariable() function of the main class is not called. 在开始之前,我还应该提到,当您创建class B对象时,不会调用主类的printVariable()函数。 Instead, always the printVariable() of B will be called. 相反,总是会调用B的printVariable()

Keeping this in mind, when you have variable = null , the execution for B's constructor will begin. 记住这一点,当你有variable = null ,B的构造函数的执行将开始。 First Main() will be called, which will call the printVariable() method. 将调用First Main() ,它将调用printVariable()方法。 At last, variable=null , will be called overwriting the variable variable. 最后, variable=null ,将被称为覆盖variable变量。

In the other case, where you do not initialize variable=null , the variable set by the printVariable() function will not be overwritten, hence you get what you were expecting. 在另一种情况下,如果你没有初始化variable=nullprintVariable()函数设置的variable将不会被覆盖,因此你得到的是你所期望的。

In summary, this is the order of execution of statements, when you do new B() : 总之,当你执行new B()时,这是语句的执行顺序:

Main()     //super constructor
  B#printVariable()
  initializtion of variables in B's constructor (if any) [i.e. variable=null, if present]

This is a nice exercise! 这是一个很好的运动! But it's not a fair question to ask junior developers. 但要问初级开发人员,这不是一个公平的问题。 This one is for seniors. 这个适合老年人。 But to make this text useful during the technical interview, I'd modified it by adding an argument to the Main's constructor: 但是为了使这个文本在技术访谈中有用,我通过在Main的构造函数中添加一个参数来修改它:

public Main(String something){
 printVariable();
}

If the person will answer what will happen, then remove the argument and ask the original questions. 如果该人将回答将要发生的事情,那么删除该论点并询问原始问题。 If the person won't answer - there is no need to continue - s/he is junior. 如果这个人不回答 - 没有必要继续 - 他/她是初中。

You can also remove the protected qualifier in class B and ask what will happen if you have a goal not to hire this person :) 您还可以删除B类中受保护的限定符,并询问如果您的目标是不雇用此人将会发生什么:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM