静态初始化程序在构造函数之后运行,为什么?

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

B级:

 public class B { static { System.out.println("B static block"); new A(); } public B() { System.out.println("B constructor"); } } 

我创建一个Main类,它只创建新的A:

 public class Main { public static void main(String[] args) { new A(); } } 

我得到的输出是:

 B static block A constructor B constructor A static block A constructor 

如您所见,A的构造函数在其静态初始化程序之前被调用。

我理解它与我创建的循环依赖有关,但我的印象是静态初始化器应该始终在构造函数之前运行。

发生这种情况的原因是什么(技术上在java实现中)?

是否建议一起避免静态初始化器?

 static B b = new B(); 

在此之前

 static { System.out.println("A static block"); } 

因此,您需要在打印"A static block"之前初始化B实例。

初始化B类意味着您需要创建一个A实例。 因此,在构造A实例之前,无法打印“静态块”。

是的,A的静态初始化是在构造函数启动之前启动的,但除了死锁之外,没有其他解决方案可用于您需要的序列。

请注意规范中的警告:

由于Java编程语言是multithreading的,因此初始化类或接口需要仔细同步,因为其他一些线程可能正在尝试同时初始化同一个类或接口。 作为该类或接口的初始化的一部分,还可以递归地请求类或接口的初始化; 例如,类A中的变量初始化程序可能会调用不相关的类B的方法,而该方法又可能调用类A方法。通过使用该方法, Java虚拟机的实现负责处理同步和递归初始化。以下程序[文件继续完整程序]

与其他语言一样,Java中的最佳实践基本上是为了避免循环依赖,因为它们的分辨率可能很难预测。