javastatic-initializer

Static initializing block is not working as expected


I have two classes, "Test1" and "Test0", as shown in this code.

public class Test1 {
    public static void main(String...args) {
        System.out.print(Test0.randomName);
    }
}
public class Test0 {
    public static String randomName = initRandomName();
    private static String string0;
    
    static {
        string0 = "George";
    }
    private static String initRandomName() {
        return "Mr. "+string0;
    }
}

I thought it would print Mr. George but it printed Mr. null. And I don't understand what's happening. Plz help me. Thank you.


Solution

  • JLS 12.4.2 details the initialization procedure. In particular:

    Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.

    In other words, you can imagine your Test0 class as being written like this:

    public class Test0 {
        public static String randomName;
        private static String string0;
        
        static {
            randomName = initRandomName();
            string0 = "George";
        }
    
        private static String initRandomName() {
            return "Mr. " + string0;
        }
    }
    

    So when initRandomName() is executed, string0 is still null.

    You could move the initialization of the randomName field to after the static initializer, like this:

    class Test0 {
        private static String string0;
    
        static {
            string0 = "George";
        }
    
        public static String randomName = initRandomName();
    
        private static String initRandomName() {
            return "Mr. "+string0;
        }
    }
    

    ... but that's quite brittle, relying on no-one reordering the members of the class without understanding the impact.

    If you really need initialization like this, I'd suggest declaring all the fields without initializing them, then initialize everything in the static initializer block so the ordering is obvious.