0

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;

2
  • 1
    "This indicates that the Line1 in MyClass is not called by the time the method getStaticSchema is called." or that it is MyUtils.staticSchema that simply returns null. Commented Mar 19, 2021 at 17:16
  • 2
    Please provide a minimal reproducible example. Do you have a circular initialization setup? Commented Mar 19, 2021 at 17:19

1 Answer 1

6

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks for your reply. I will check if a circular dependency caused this. It is quite possible because I am sure MyUtils.staticSchema will never return null.
Putting breakpoints in MyClass.getStaticSchema() and MyUtils.staticSchema(name, schema) would show you the order in which they are executed. Note that debugging this might result in weird behaviour, as debugging during class initialization can easily influence the class initalization order and thus hide/change/destroy the behaviour/bug. System.out.println might be a simple tool, but it's your friend in these kinds of cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.