调用静态方法时未初始化静态 Java 字段

时间:2021-03-19 17:13:52

标签: java

我有一个这样定义的类:

class MyClass {
    private static final String name = "<some string>";
    private static final String schema = "{<some json here>}";
    public static final MySchemaObject schemaObj = MyUtils.staticSchema(name, schema);   // Line1

    public static MySchemaObject getStaticSchema() {
        return schemaObj;
    }
}

另一个类在静态初始化器中调用这个类:

class AnotherClass {
    private static final MySchemaObject schemaObject = MyClass.getStaticSchema();   <===== Always null
    ........
}

在类 AnotherClass 中,静态变量 schemaObject 始终初始化为 null。这表明在调用方法 Line1 时未调用 MyClass 中的 getStaticSchema

我的理解是在调用任何静态方法之前创建静态变量,但似乎并非如此。

有人可以帮我理解这个吗?

编辑:MyUtils.staticSchema 永远不会返回 null;

1 个答案:

答案 0 :(得分:6)

有两个可能的原因:

  1. MyUtils.staticSchema 返回 null
  2. AnotherClass 由于循环依赖,在 MyClass 的初始化过程中被初始化。

我假设您已经验证/排除了选项 #1,所以我将专注于第二个:

依赖于其他类的非平凡静态字段初始化可能会出现问题,因为它会在类初始化中引入长依赖链甚至依赖循环。

如果 class A 在类初始化期间调用 class B 的方法,而 class B 在类初始化期间调用 class A 的方法,则存在循环:意味着某些代码会看到半初始化的类。

如果您的 MyClass 在类初始化期间以某种方式(直接或间接)接触 AnotherClass 那么很可能对 MyClass.getStaticSchema() 的调用实际上在 before { {1}} 已初始化。

最好的解决方案是让任何类的类初始化依赖于尽可能少的类。

演示问题的简单示例:

schemaObj

如果您尝试打印 class A { public static final String CONSTANT_IN_A = B.CONSTANT_IN_B; public static final String ANOTHER_VALUE = "Value " + (Math.random() * 0 + 1); } class B { public static final String CONSTANT_IN_B = "B version of " + A.ANOTHER_VALUE; } ,输出将是 A.CONSTANT_IN_A,因为在 B version of null 的初始化过程中,B.CONSTANT_IN_B 中的字段 ANOTHER_VALUE 还没有已初始化。