Java 是什么保证了从另一个类调用静态方法';s静态块是否按预期工作?

Java 是什么保证了从另一个类调用静态方法';s静态块是否按预期工作?,java,static,jvm,static-methods,static-block,Java,Static,Jvm,Static Methods,Static Block,类A包含: 静态字符串 在类的静态映射中填充的静态映射 挡块 一个静态方法,比如getStr(),它返回一个从静态方法构建的字符串 字符串 类B包含: 静态Map 使用a.getStr() B的静态块是否总是成功填充其映射?我假设JVM能够处理这个问题。加载类时,静态块的执行顺序是否会有任何问题,这反过来又不能保证B正确填充映射?我想确定一下,也许我能理解这背后的机制。如果两个类在静态初始化期间有循环依赖,事情就会变得棘手。Java确实有一个严格定义的初始化过程,并且在检测到递归时会退出

A
包含:

  • 静态
    字符串
  • 在类的静态映射中填充的静态映射 挡块
  • 一个静态方法,比如
    getStr()
    ,它返回一个从静态方法构建的
    字符串
    
    字符串
B
包含:

  • 静态
    Map
  • 使用
    a.getStr()

B
的静态块是否总是成功填充其映射?我假设JVM能够处理这个问题。加载类时,静态块的执行顺序是否会有任何问题,这反过来又不能保证
B
正确填充映射?我想确定一下,也许我能理解这背后的机制。

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

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

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


作为循环依赖的一个例子,假设
类A扩展了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。

为什么不能成功填充?更重要的是,为什么只是有时?如果初始化中存在周期性依赖,则可能无法成功填充。@mastov-如果是这样,那么是否不能保证B始终会成功填充?哪里存在周期性依赖?我认为B依赖于A,但不是相反,除非你想说A的映射依赖于B的静态块(如果是这样的话,可以澄清一下)。这里没有足够的信息来验证是否存在循环依赖性:我们没有类及其所有依赖性的实现。因此,谨慎的回答是:不,它不会总是被成功地填充;他们可能不是这样的一个原因是周期性依赖。谢谢你的回答。我还发现这一点很有帮助: