我有2个班级:
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实现中)?
建议一起避免使用静态初始化程序吗?
答案 0 :(得分:24)
static B b = new B();
之前
static {
System.out.println("A static block");
}
因此,您需要在打印"A static block"
之前初始化B实例。
初始化B类意味着您需要创建一个A实例。因此,在构造A实例之前,无法打印“静态块”。
是的,在构造函数启动之前,A的静态初始化是启动但是,除了死锁之外,没有其他解决方案可以解决所需的序列。
请注意the specification中的警告:
因为Java编程语言是多线程的,所以初始化 一些类或接口需要仔细同步,因为有些 其他线程可能正在尝试初始化相同的类或接口 同时。 还有初始化的可能性 可以递归地请求类或接口作为其一部分 初始化该类或接口;例如,一个变量 A类中的初始化程序可能会调用不相关的B类的方法, 这可能反过来调用A类的方法。。的实现 Java虚拟机负责照顾 使用以下方法进行同步和递归初始化 程序[文件继续完整的程序]
与其他语言一样,Java中的最佳实践基本上是为了避免循环依赖,因为它们的分辨率可能很难预测。