[英]Weird static initialization in Java when using Reflection
Given the following code-snippet I get the output "B" and "error": 给定以下代码片段,我得到输出“B”和“错误”:
public class Test {
private static class A {
static final B c = new B();
}
private static class B extends A {
static final B c = A.c;
}
public static void main(String[] args) throws Exception {
for(Class<?> 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("error");
}
}
}
But it gets even more bizarre. 但它变得更奇怪了。 If I comment-out the for-loop I get no output - so no error. 如果我注释掉for循环,我得不到输出 - 所以没有错误。 Also if I access the field Bc directly without reflection before doing the reflection stuff the problem does not occur. 此外,如果我在进行反射之前直接访问字段Bc而没有反射,则不会发生问题。 Why is that so and how can I fix it? 为什么会这样,我该如何解决?
The problem is not related with reflection, is related with the order in which classes are initialized. 问题与反射无关,与初始化类的顺序有关。
If class A is initialized first, it has a dependency in class B, class B tries to initialize Bc to a static field of A, but this field is still null. 如果首先初始化类A,它在类B中具有依赖性,则类B尝试将Bc初始化为静态字段A,但此字段仍为空。
If the class B is initialized first, it has a dependency in class A, the class A is initialized and Ac is set to a new B instance and Bc is initialized correctly. 如果首先初始化类B,它在类A中具有依赖性,则初始化类A并且将Ac设置为新的B实例并且正确地初始化Bc。
To make an example more simple, this code shows the problem simplified: 为了使示例更简单,此代码显示了简化的问题:
public static void main(String[] args) throws Exception {
System.out.println(A.c);
System.out.println(B.c);
}
Output: 输出:
Test$B@f72617
null
And this other example: 另一个例子是:
public static void main(String[] args) throws Exception {
System.out.println(B.c);
System.out.println(A.c);
}
Output: 输出:
Test$B@f72617
Test$B@f72617
To solve the problem you could change your design to remove the circular dependency or make sure the classes are initialized in the right order. 要解决此问题,您可以更改设计以删除循环依赖项或确保按正确的顺序初始化类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.