gpt4 book ai didi

java - 初始化相互引用的静态字段时出错

转载 作者:行者123 更新时间:2023-11-30 07:27:27 25 4
gpt4 key购买 nike

我想我在我的一些代码中发现了一个错误,尽管它似乎并没有在所有情况下都出现。我希望比我聪明的人可以明确地说“是的,这是一个错误”,并且更好的是,建议另一种替代方案来替代我的实现。

我相信错误的根源是两个类的静态字段是如何初始化的;一个(在 FooClass 中)通过引用另一个字段进行初始化,而一个(在 MyUtility 中)通过创建类型为 Foo 的对象进行初始化.抱歉,听起来不对;解释从来不是我的强项。

我花了一天的大部分时间来尝试减少问题,并且有一些可运行的东西似乎可以证明问题。

public class Tester {

static class FooClass {
static final FooClass ITS_FOO = MyUtility.MY_FOO;
}

static class MyUtility {
static final FooClass MY_FOO = new FooClass();

static FooClass create() {
return new FooClass();
}
}

public static void main(String[] args) {
System.out.println("utility's: " + MyUtility.create()); // Line "A"
System.out.println("class's: " + FooClass.ITS_FOO); // Line "B"
}
}

我意识到这个设计看起来很奇怪,但不会试图证明它的合理性(实际代码的结构也“奇怪”,但在具有不同可见性等的单独类中)。我非常感谢有关更好的方法的建议。

问题的要点(至少对于这个程序)是 FooClass.ITS_FOO 字段在 B 行执行时为 null。如果我调换 A 行和 B 行的顺序,两个字段都不是 null

我见过像 In what order do static initializer blocks in Java run? 这样的问题, 但既不是 Java Language Spec似乎描述了这种相互引用的初始化是如何完成的。

不幸的是,这个示例与我们的实际实现相去甚远,我可能会花费同样多的时间来翻译任何解决方案,但为了得到一些解释,这是值得的。

最佳答案

是的,如果您强制 FooClass 先初始化,那么这将触发 MyUtility 初始化。 MY_FOO 的初始化程序将继续进行,因为 FooClass 已经在此线程中初始化,所以 MY_FOO 将是非空的.

另一方面,如果您从 FooClass 构造函数(当前只是默认设置)中观察 ITS_FOO,您会发现它在那里为空...

此行为在规范中有详细记录 - 您链接到的部分提供了所有详细信息 - 但基本上它是一个非常糟糕的主意有两种类型静态初始值设定项相互引用。不要试图以微妙的方式修复它:摆脱依赖。我意识到这可能很痛苦,但实际上,不值得考虑任何其他修复方法。

执行该修复的一种方法可能是使用不依赖于任何其他类型的静态初始化程序提取第三种类型,并且其他两种类型类型可以依赖。

当然,在你的静态初始化器中做的更少也是有帮助的:)

关于java - 初始化相互引用的静态字段时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9707710/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com