3

A包含:

  • 静止的Strings
  • 填充在类的静态Map块中的静态
  • 一个静态方法,例如getStr(),它返回String从静态构建的 Strings

B包含:

  • 一个静态的Map
  • 填充Mapusing的静态块A.getStr()

B的静态块总是能成功填充它的地图吗?我假设JVM能够处理这个。加载类时执行静态块的顺序是否存在任何问题,这反过来又不能保证B正确填充地图?我想确定,也许了解这背后的机制。

4

1 回答 1

2

如果两个类在静态初始化期间具有循环依赖关系,事情就会变得棘手。Java 确实有一个严格定义的初始化过程,并在检测到递归时退出。但是,这将取决于在运行时首先触发哪个类初始化。这意味着部分初始化的类可能是可见的(在您的情况下,看到 null getStr)。

如果从两个不同的线程初始化两个类,循环依赖不仅令人困惑,甚至可能导致死锁。因此,应该不惜一切代价避免它。两方之间的循环依赖总是可以通过引入第三方来解决。

没有循环依赖,一个类总是被完全初始化;在您的情况下,当 B 调用时A.getStr(),它必须A是完全初始化的情况,并getStr()返回所需的值。


作为循环依赖的一个例子,假设class A extends B.

如果B先初始化(例如有人调用B.something),则没有问题;B初始化过程中遇到A.getStr,会触发A初始化;完成后,A.getStr然后执行,并看到一个正确初始化的字段。

但是,如果A是先初始化,那就麻烦了;它将触发超类 B 的初始化;当 B 调用时A.getStr,VM 看到它A已经在初始化过程中,所以它会后退并且不会尝试完成 A 的初始化;A.getStr将简单地看到null

为了打破这个循环,我们可以将 A 中 B 依赖的东西移动到 A'。A 和 B 都取决于 A'。

于 2015-09-30T22:08:49.353 回答