A
类包含:
- 静态
字符串
- 一个静态
Map
,填充在类的静态 阻止 - 一个静态方法,比如
getStr()
,它返回一个从静态构建的String
字符串
B
类包含:
- 静态
map
- 使用
A.getStr()
填充
Map
的静态 block
B
的静态 block 总是 会成功填充它的 map 吗?我假设 JVM 能够处理这个问题。加载类时静态 block 的执行顺序是否存在任何问题,进而无法保证 B
正确填充 map ?我想确定,也许了解这背后的机制。
最佳答案
如果两个类在静态初始化期间有循环依赖,事情就会变得棘手。 Java 确实有一个严格定义的初始化过程,并在检测到递归时退出。但是,这将取决于在运行时首先触发哪个类初始化。这意味着部分初始化的类可能是可见的(在您的情况下,看到一个空的 getStr
)。
如果两个类从两个不同的线程初始化,循环依赖不仅会造成混淆,甚至可能导致死锁。因此,应该不惜一切代价避免它。两方之间的循环依赖总是可以通过引入第 3 方来解决。
没有循环依赖,类总是被完全初始化;在您的情况下,当 B 调用 A.getStr()
时,一定是 A
已完全初始化,并且 getStr()
返回所需的值。
作为循环依赖的一个例子,假设class A extends B
。
如果B
先被初始化(例如,有人调用B.something
),没有问题; B在初始化的过程中,遇到A.getStr
,就会触发A的初始化;完成后,A.getStr
将被执行,并看到一个正确初始化的字段。
但是,如果先初始化A
,就会有麻烦;它将触发父类(super class) B 的初始化;当 B 调用 A.getStr
时,VM 看到 A
已经在初始化过程中,因此它会退出,不会尝试完成 A 的初始化; A.getStr
只会看到 null
。
要打破这个循环,我们可以将 A 中 B 依赖的东西移动到 A'。 A 和 B 都将依赖于 A'。
关于java - 是什么保证从另一个类的静态 block 调用静态方法按预期工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32876204/