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? 以及为什么构造函数在静态初始化程序之前运行?
答案 0 :(得分:1)
初始化类时,它将按照它们在代码中出现的顺序执行所有static {...}
和静态字段初始值设定项(请参阅JLS 12.4.2,特别是列表中的第9步)那里的步骤)。在您的示例中,有两个这样的初始值设定项:
private static DataFactory ourInstance = new DataFactory();
static {...}
阻止所以,第一个先发生。它实例化一个对象并将其引用分配给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节)。
正如您所看到的,在初始化类时首先调用构造函数,然后在构造函数调用之后,然后调用静态块。