Java: initialization sequence of object

2019-04-09 08:17发布

There is a code which is given as a task for a junior Java developers. I use Java during five years and this piece of code completely confusing me:

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; to 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:

  • We go to the root of the class hierarchy (for Java it is always Object class), when we come to this root parent class:
    • 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

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;
  2. We go to the part class Main;
  3. Initialize main.variable with null;
  4. Then we move to the default constructor of class Main;
  5. Constructor calls method b.printVariable() in class Main; (Why doesn't it call main.printvariable? We don't have this key word here.)
  6. The field b.variable "variable is initialized in B Class"
  7. Now we come back to the class B;
  8. We should initialize field b.variable with null value, am I right?;
  9. The default constructor of class B executed

Please, can someone give a complete and full explanation of how this inheritance inizialisation sequence works. And why changing String variable = null; to String variable; leads to another output.

3条回答
对你真心纯属浪费
2楼-- · 2019-04-09 08:42

First, you need to understand, what happens when you write 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. Instead, always the printVariable() of B will be called.

Keeping this in mind, when you have variable = null, the execution for B's constructor will begin. First Main() will be called, which will call the printVariable() method. At last, variable=null, will be called overwriting the variable 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.

In summary, this is the order of execution of statements, when you do new B():

Main()     //super constructor
  B#printVariable()
  initializtion of variables in B's constructor (if any) [i.e. variable=null, if present]
查看更多
叼着烟拽天下
3楼-- · 2019-04-09 08:49

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:

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 :)

查看更多
别忘想泡老子
4楼-- · 2019-04-09 08:58

The sequence is:

  1. Main -> "Hello"
  2. Main -> new B()
  3. B() -> Main() -> b.printVariable() -> sets the variable
  4. Back to initialising B, so variable=null occurs.

So basically, the super object Main() is constructed before any intialisation events of class B. Which means variable=null occurs later. This makes sense as otherwise B could break the initialisation of 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.

查看更多
登录 后发表回答