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

ZZZ*_*ZZZ 0 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

class AnotherClass {
    private static final MySchemaObject schemaObject = MyClass.getStaticSchema();   <===== Always null
    ........
}
Run Code Online (Sandbox Code Playgroud)

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

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

有人可以帮我理解这一点吗?

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

Joa*_*uer 6

有两个可能的原因:

  1. MyUtils.staticSchema返回null或
  2. AnotherClassMyClass由于循环依赖,在初始化期间初始化。

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

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

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

如果您在类初始化期间MyClass以某种方式(直接或间接)接触AnotherClass,则很可能在初始化之前MyClass.getStaticSchema()实际执行了调用。 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;
}
Run Code Online (Sandbox Code Playgroud)

如果您尝试打印A.CONSTANT_IN_A输出将会是B version of null,因为在初始化期间B.CONSTANT_IN_B字段ANOTHER_VALUEinA还没有被初始化。