Avi*_*gal 24 java constructor static-initialization
我有2个班:
A类:
public class A {
static B b = new B();
static {
System.out.println("A static block");
}
public A() {
System.out.println("A constructor");
}
}
Run Code Online (Sandbox Code Playgroud)
B级:
public class B {
static {
System.out.println("B static block");
new A();
}
public B() {
System.out.println("B constructor");
}
}
Run Code Online (Sandbox Code Playgroud)
我创建一个Main类,它只创建新的A:
public class Main {
public static void main(String[] args) {
new A();
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是:
B static block
A constructor
B constructor
A static block
A constructor
Run Code Online (Sandbox Code Playgroud)
如您所见,A的构造函数在其静态初始化程序之前被调用.
我理解它与我创建的循环依赖有关,但我的印象是静态初始化器应该始终在构造函数之前运行.
发生这种情况的原因是什么(技术上在java实现中)?
是否建议一起避免静态初始化器?
Den*_*ret 24
static B b = new B();
Run Code Online (Sandbox Code Playgroud)
在此之前
static {
System.out.println("A static block");
}
Run Code Online (Sandbox Code Playgroud)
因此,您需要在打印之前初始化B实例"A static block".
初始化B类意味着您需要创建一个A实例.因此,在构造A实例之前,无法打印"静态块".
是的,A的静态初始化是在构造函数启动之前启动的,但除了死锁之外,没有其他解决方案可用于您需要的序列.
请注意规范中的警告:
由于Java编程语言是多线程的,因此初始化类或接口需要仔细同步,因为某些其他线程可能正在尝试同时初始化相同的类或接口.作为该类或接口的初始化的一部分,还可以递归地请求类或接口的初始化; 例如,类A中的变量初始化程序可能会调用不相关的类B的方法,而该方法又可能调用类A的方法.通过使用该方法, Java虚拟机的实现负责处理同步和递归初始化.以下程序[文件继续完整程序]
Java中的最佳实践与其他语言一样,基本上是为了避免循环依赖,因为它们的分辨率可能很难预测.