java - 静态初始化器在构造函数之后运行,为什么?

标签 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");
     }
}

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 实例之前无法打印“静态 block ”。

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

注意 the specification 中的警告:

Because the Java programming language is multithreaded, initialization of a class or interface requires careful synchronization, since some other thread may be trying to initialize the same class or interface at the same time. There is also the possibility that initialization of a class or interface may be requested recursively as part of the initialization of that class or interface; for example, a variable initializer in class A might invoke a method of an unrelated class B, which might in turn invoke a method of class A. The implementation of the Java virtual machine is responsible for taking care of synchronization and recursive initialization by using the following procedure [the doc goes on with the complete procedure]

在 Java 和其他语言中的最佳实践基本上是避免循环依赖,因为它们的解决方案可能很难预测。

关于java - 静态初始化器在构造函数之后运行,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13948170/

相关文章:

java - 如何在 Java 中使用 Bigdecimal 数学运算获取值

Java泛型的声明有点复杂?

c - 静态 pthreads 互斥体初始化

c++ - 静态初始化时能否安全创建线程?

android - 防止 Proguard 删除 fragment 的空构造函数

c - 为什么编译器认为 GCC 中嵌套函数(GNU 扩展)的地址为 "not constant"?

java - 在真实设备上运行应用程序时出现 NoClassDefFoundError,但在模拟器上运行时不会出现 NoClassDefFoundError

java - 属性比较问题

c++ - 将工作委托(delegate)给父类(super class)的构造函数

c++ - 自动创建对象,如何控制/增加名称?