静态初始化程序在构造函数之后运行,为什么? [英] Static initializer runs after the constructor, why?

查看:105
本文介绍了静态初始化程序在构造函数之后运行,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有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:

I create a Main class which just creates new 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的构造函数在其静态初始化程序之前被调用。

As you can see, the constructor of A is invoked before its static initializer.

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

I understand it got something to do with the cyclic dependency I created but I was under the impression the static initializer should always run before the constructor.

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

是否建议一起避免使用静态初始值设定项?

推荐答案

static B b = new B();

之前

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

因此,您需要在打印<$ c $之前初始化B实例c>静态块。

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

And initializing the B class means you need to create a A instance. So there's no way for "A static block" to be printed before the A instance is constructed.

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

Yes, the static initialization of A is launched before the constructor is launched but, apart deadlocking, there would be no other solution to the sequence you require.

注意规范


因为Java编程语言是多线程,初始化
类或接口需要仔细同步,因为一些
其他线程可能正在尝试同时初始化同一个类或接口
作为
初始化该类或接口的一部分,还可以递归地请求
初始化类或接口;例如,类A中的变量
初始值设定项可能会调用不相关的类B的方法,
可能会调用类A的方法。

的实现Java虚拟机负责通过使用以下
过程来处理
同步和递归初始化[文档继续完整的过程]

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

A best practice, in Java as in other languages, is basically to avoid cyclic dependencies as their resolution may be very hard to predict.

这篇关于静态初始化程序在构造函数之后运行,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆