使用反射时Java中奇怪的静态初始化

使用反射时Java中奇怪的静态初始化,java,reflection,static,initialization,Java,Reflection,Static,Initialization,给定以下代码段,我得到输出“B”和“error”: 公共类测试{ 专用静态A类{ 静态最终B c=新B(); } 私有静态类B扩展了{ 静态最终B c=A.c; } 公共静态void main(字符串[]args)引发异常{ for(类cls:Test.Class.getDeclaredClasses()){ if(cls.getDeclaredFields()[0]。get(null)==null){ System.out.println(cls.getSimpleName()); } } i

给定以下代码段,我得到输出“B”和“error”:

公共类测试{
专用静态A类{
静态最终B c=新B();
}
私有静态类B扩展了{
静态最终B c=A.c;
}
公共静态void main(字符串[]args)引发异常{
for(类cls:Test.Class.getDeclaredClasses()){
if(cls.getDeclaredFields()[0]。get(null)==null){
System.out.println(cls.getSimpleName());
}
}
if(B.class.getDeclaredField(“c”).get(null)==null){
System.out.println(“错误”);
}
}
}
但它变得更加奇怪。如果我注释掉for循环,则不会得到任何输出,因此不会出现错误。另外,如果我在做反射之前没有反射直接访问字段B.c,那么问题就不会发生。
为什么会这样?我如何解决它?

问题与反射无关,与类的初始化顺序有关

如果首先初始化类A,则它在类B中具有依赖关系,类B尝试将B.c初始化为静态字段A,但该字段仍然为空

如果先初始化类B,则它在类a中具有依赖关系,初始化类a,将a.c设置为新的B实例,并正确初始化B.c

为了使示例更简单,此代码显示了简化的问题:

public static void main(String[] args) throws Exception {
    System.out.println(A.c);
    System.out.println(B.c);
}
输出:

Test$B@f72617
null
Test$B@f72617
Test$B@f72617
还有另一个例子:

public static void main(String[] args) throws Exception {
    System.out.println(B.c);
    System.out.println(A.c);
}
输出:

Test$B@f72617
null
Test$B@f72617
Test$B@f72617

要解决此问题,您可以更改设计以删除循环依赖项,或者确保类以正确的顺序初始化。

我将重构代码以删除两个类之间的循环依赖项。这几乎肯定会解决您的问题。关闭。但是,问题不在于类的加载顺序。这是按照它们初始化的顺序进行的。或者更准确地说,是各个类的静态初始化发生的顺序。@StephenC感谢您的评论。这就是我的观点。我重新改写了我的答案,试图用术语更精确。