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

时间:2012-12-19 08:22:46

标签: 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实现中)?

建议一起避免使用静态初始化程序吗?

1 个答案:

答案 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中的最佳实践基本上是为了避免循环依赖,因为它们的分辨率可能很难预测。