是什么保证从另一个 class 的静态块调用静态方法按预期工作?
What guarantees that this call to a static method from another class's static block works as expected?
Class A
包含:
- 静态
Strings
- 填充在 class 静态中的静态
Map
块
- 一个静态方法,比如
getStr()
,returns 一个从静态构建的 String
Strings
Class B
包含:
- 静态
Map
- 使用
A.getStr()
填充 Map
的静态块
B
的静态块总是会成功填充它的地图吗?我假设 JVM 能够处理这个问题。加载 classes 时静态块的执行顺序是否存在任何问题,进而无法保证 B
正确填充地图?我想确定一下,也许可以了解这背后的机制。
如果两个 classes 在静态初始化期间有循环依赖,事情就会变得棘手。 Java 确实有一个严格定义的初始化程序,并在检测到递归时退出。然而,这将取决于在运行时首先触发哪个 class 初始化。这意味着部分初始化的 class 可能是可见的(在您的情况下,看到空 getStr
)。
循环依赖不仅令人困惑,如果两个 classes 从两个不同的线程初始化,它甚至可能导致死锁。因此,应该不惜一切代价避免它。两方之间的循环依赖总是可以通过引入第 3 方来解决。
没有循环依赖,class总是被完全初始化;在您的情况下,当 B 调用 A.getStr()
时,一定是 A
已完全初始化,并且 getStr()
returns 所需的值。
作为循环依赖的例子,假设class A extends B
。
如果B
先初始化(例如有人调用B.something
),没有问题; B在初始化的过程中,遇到A.getStr
,就会触发A的初始化;完成后,A.getStr
将被执行,并看到一个正确初始化的字段。
但是,如果A
先初始化,就会有麻烦;会触发superclass B的初始化;当 B 调用 A.getStr
时,VM 看到 A
已经在初始化过程中,因此它会退出,不会尝试完成 A 的初始化; A.getStr
只会看到 null
。
为了打破这个循环,我们可以将A中B依赖的东西移动到A'。 A 和 B 都将依赖于 A'。
Class A
包含:
- 静态
Strings
- 填充在 class 静态中的静态
Map
块 - 一个静态方法,比如
getStr()
,returns 一个从静态构建的String
Strings
Class B
包含:
- 静态
Map
- 使用
A.getStr()
填充
Map
的静态块
B
的静态块总是会成功填充它的地图吗?我假设 JVM 能够处理这个问题。加载 classes 时静态块的执行顺序是否存在任何问题,进而无法保证 B
正确填充地图?我想确定一下,也许可以了解这背后的机制。
如果两个 classes 在静态初始化期间有循环依赖,事情就会变得棘手。 Java 确实有一个严格定义的初始化程序,并在检测到递归时退出。然而,这将取决于在运行时首先触发哪个 class 初始化。这意味着部分初始化的 class 可能是可见的(在您的情况下,看到空 getStr
)。
循环依赖不仅令人困惑,如果两个 classes 从两个不同的线程初始化,它甚至可能导致死锁。因此,应该不惜一切代价避免它。两方之间的循环依赖总是可以通过引入第 3 方来解决。
没有循环依赖,class总是被完全初始化;在您的情况下,当 B 调用 A.getStr()
时,一定是 A
已完全初始化,并且 getStr()
returns 所需的值。
作为循环依赖的例子,假设class A extends B
。
如果B
先初始化(例如有人调用B.something
),没有问题; B在初始化的过程中,遇到A.getStr
,就会触发A的初始化;完成后,A.getStr
将被执行,并看到一个正确初始化的字段。
但是,如果A
先初始化,就会有麻烦;会触发superclass B的初始化;当 B 调用 A.getStr
时,VM 看到 A
已经在初始化过程中,因此它会退出,不会尝试完成 A 的初始化; A.getStr
只会看到 null
。
为了打破这个循环,我们可以将A中B依赖的东西移动到A'。 A 和 B 都将依赖于 A'。