static Java field not initialized when a static method is called

I have a class defined like this:

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;
    }
}

Another class calls this class in a static initializer:

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

In the class AnotherClass, the static variable schemaObject is always initialzied into null. This indicates that the Line1 in MyClass is not called by the time the method getStaticSchema is called.

My understanding is that static variable are created before any static method can be called, but it seems not the case.

Can someone please help me understand this?

EDIT: MyUtils.staticSchema will never retur null;

Answer

There are two possible reasons:

  1. MyUtils.staticSchema returns null or
  2. AnotherClass is initialized during the initialization of MyClass due to a cyclic dependency.

I assume that you’ve already verified/ruled out option #1 so I’ll focus on the second one:

Non-trivial static field initialization that depends on other classes can be problematic, because it can introduce long dependency chains and even dependency loops in class initialization.

If class A calls a method of class B during class initialization and class B calls a method of class A during class initialization, then there’s a loop: that means that some code will see half-initialized classes.

If your MyClass somehow (directly or indirectly) touches AnotherClass during class initialization then it’s quite possible tha the call to MyClass.getStaticSchema() is actually executed before schemaObj is initialized.

The best solution is to make the class initialization of any class depend on as few classes as possible.

Simple sample demonstrating the problem:

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;
}

If you try to print A.CONSTANT_IN_A the output will be B version of null, because during the initialization of B.CONSTANT_IN_B the field ANOTHER_VALUE in A will not yet have been initialized.

Leave a Reply

Your email address will not be published. Required fields are marked *