静态初始化程序在构造函数之后运行,为什么?
问题内容:
我有2节课:
Class A:
public class A {
static B b = new B();
static {
System.out.println("A static block");
}
public A() {
System.out.println("A constructor");
}
}
Class B:
public class B {
static {
System.out.println("B static block");
new A();
}
public B() {
System.out.println("B constructor");
}
}
I create a Main class which just creates new A:
public class Main {
public static void main(String[] args) {
new A();
}
}
The output I get is:
B static block
A constructor
B constructor
A static block
A constructor
如您所见,A的构造函数在其静态初始值设定项之前被调用。
我了解它与我创建的循环依赖关系有关,但我印象中静态初始化程序应始终在构造函数之前运行。
发生这种情况的原因是什么(技术上在Java实现中)?
是否建议同时避免使用静态初始化程序?
问题答案:
static B b = new B();
is before
static {
System.out.println("A static block");
}
因此,您需要在打印之前初始化B实例”A static block”。
初始化B类意味着您需要创建一个A实例。因此,
在
构造A实例之前,无法打印“静态块” 。
是的,在构造函数启动之前就启动了A的静态初始化,
但是除了死锁之外,没有其他解决方案可用于
您需要的序列。
Note the warning in the
specification
:
因为Java编程语言是多线程的,所以
类或接口的初始化需要仔细的同步,因为某些其他线程
可能试图同时初始化同一类或接口。
还
可能会递归地请求类或接口的初始化,作为该类或接口的初始化的一部分
;例如,类A中的变量初始值设定项可能会调用
不相关的类B的方法,而后者又可能会调用类
A的方法。Java虚拟机的实现负责
通过使用同步来实现同步和递归初始化。
遵循以下步骤[文档继续执行完整步骤]
与其他语言一样,使用Java的最佳实践基本上是避免循环依赖,因为它们的分辨率可能很难预测。