why this weird order of constructor/static initializer/static member function in java?

吃可爱长大的小学妹 提交于 2019-12-10 10:43:22

问题


public class DataFactory {
  private static DataFactory ourInstance = new DataFactory();
  static {
    System.out.println("static initialize");
  }

  private DataFactory() {
    System.out.println("constructor");
  }

  public static void doNothing() {
    System.out.println("inside doNothing");
  }
}

public class App {
  public static void main(String[] args) {
    System.out.println("main start");
    DataFactory.doNothing();
}

And After I run it, here is the printed sequence:

main start

constructor

static initialize

inside doNothing

Why calling DataFactory.doNothing() will trigger Constructor? and why constructor is running before the static initializer?


回答1:


When the class is initialized, it'll execute all of the static {...} and static field initializers, in the order they appear in the code (see JLS 12.4.2, and in particular step 9 in the list of steps there). In your example, there are two such initializers:

  1. private static DataFactory ourInstance = new DataFactory();
  2. The static {...} block

So, the first one happens first. It instantiate an object and assigns its reference to ourInstance. To instantiate the object, it needs to call the constructor, which it does (as you saw).

When that's done, the static block is executed, which prints "static initialize."

At this point, the class is initialized, and the method doNothing can finally be invoked.




回答2:


It's invoking the constructor because you are creating an instance of DataFactory inside the same DataFactory; so it needs to call the constructor once in order to be able to instantiate it. Comment or delete the private static DataFactory ourInstance = new DataFactory(); line and the constructor call is not going to happens.

A static initializer is executed right after the class is initialized.




回答3:


Sorry to tell that Rod_Algonquin is incomplete and Machina too. The right answer is that:

"Static Initialization Blocks run when the class is first loaded"

So, you are correct to ask "why the constructor is run before static?!".

How can? And there is a rule for initialization blocks (statics and instance).

The order in which initialization blocks appear in a class matters.

Just swap the order of your static initialization block to the static instantiation to see what happen:

    public class DataFactory {
        static { //// SWAPPED HERE
            System.out.println("static initialize");
          }

        ///// SWAPPED HERE
        private static DataFactory ourInstance = new DataFactory();


      private DataFactory() {
        System.out.println("constructor");
      }

      public static void doNothing() {
        System.out.println("inside doNothing");
      }
    }

OUTPUT:

main start

static initialize

constructor

inside doNothing




回答4:


Your static field initialization calls the constructor.

In the end, the code that initializes the field "ourInstance" is also part of the static initializer.

So what is actually happening is:

public class DataFactory {
  private static DataFactory ourInstance;

  static {      
    outInstance = new DataFactory(); // 2 
    System.out.println("static initialize"); // 4
  }

  private DataFactory() {
    System.out.println("constructor"); // 3
  }

  public static void doNothing() {
    System.out.println("inside doNothing"); // 6
  }
}

public class App {
  public static void main(String[] args) {
    System.out.println("main start"); // 0
    DataFactory.doNothing(); // 1 (static init) and 5 (method call)
  }
}



回答5:


Here is the JLS documentation for the constructor:

Constructors are invoked by class instance creation expressions (§15.9)

And the JLS documentation for the static block:

A static initializer declared in a class is executed when the class is initialized (§12.4.2).

As you can see the constructor is first called when the class is initialized and then right after the constructor call then the static block is then called.



来源:https://stackoverflow.com/questions/29359923/why-this-weird-order-of-constructor-static-initializer-static-member-function-in

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!