为什么这个奇怪的构造函数/静态初始化器/静态成员函数在java中的顺序?

时间:2015-03-31 03:06:00

标签: java constructor static-methods static-members

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();
}

在我运行之后,这是打印的序列:

主要开始

构造

静态初始化

在doNothing里面

为什么调用DataFactory.doNothing()会触发Constructor? 以及为什么构造函数在静态初始化程序之前运行?

5 个答案:

答案 0 :(得分:1)

初始化类时,它将按照它们在代码中出现的顺序执行所有static {...}和静态字段初始值设定项(请参阅JLS 12.4.2,特别是列表中的第9步)那里的步骤)。在您的示例中,有两个这样的初始值设定项:

  1. private static DataFactory ourInstance = new DataFactory();
  2. static {...}阻止
  3. 所以,第一个先发生。它实例化一个对象并将其引用分配给ourInstance。要实例化对象,需要调用构造函数(如您所见)。

    完成后,执行静态块,打印“static initialize。”

    此时,该类已初始化,最终可以调用方法doNothing

答案 1 :(得分:0)

它正在调用构造函数,因为您在同一DataFactory内创建了DataFactory的实例;所以它需要调用构造函数一次才能实例化它。注释或删除private static DataFactory ourInstance = new DataFactory();行,构造函数调用不会发生。

在初始化类之后立即执行static初始化程序。

答案 2 :(得分:0)

很抱歉告诉Rod_Algonquin不完整,还有Machina。正确的答案是:

  

“静态初始化块在首次加载类时运行”

所以,你问“为什么构造函数在静态之前运行?!”是正确的。

怎么样?初始化块(静态和实例)有一个规则。

  

初始化块在类中出现的顺序很重要。

只需将静态初始化块的顺序交换到静态实例化,看看会发生什么:

    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");
      }
    }

输出:

主要开始

静态初始化

构造

在doNothing里面

答案 3 :(得分:0)

您的静态字段初始化会调用构造函数。

最后,初始化字段的代码" ourInstance"也是静态初始化程序的一部分。

所以实际发生的是:

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

答案 4 :(得分:-1)

以下是构造函数的JLS documentation

  

构造函数由类实例创建表达式(第15.9节)

调用

静态块的JLS documentation

  

在类初始化时执行类中声明的静态初始化程序(第12.4.2节)。

正如您所看到的,在初始化类时首先调用构造函数,然后在构造函数调用之后,然后调用静态块。