Order of static variable initialization, Java

They are executed in the order that you write them. If the code is:

public class Test {

    static int k = 1;
    static {k = 2;}

    public static void main(String[] args) {
        System.out.println(k);
    }

}

then the output becomes 2.

The order of initialization is: ..the class variable initializers and static initializers of the class..., in textual order, as though they were a single block.

And the values (for your code) are: k = 0 (default), then it's set to 2, then it's set back to 1.

You can check that it's actually set to 2 by running the following code:

private static class Test {

    static {
        System.out.println(Test.k);
        k = 2;
        System.out.println(Test.k);
        }
    static int k = 1;

    public static void main(String[] args) {
        System.out.println(k);
    }
}

Short answer

When the initialization of the class starts, k will have initial value of 0.

The static block (since it precedes the assignment in the declaration) is then executed, and k will be assigned 2.

Then the initializer in the declaration is executed, and k will be assigned 1.

Long explanation

Let us use this example, since your example is a bit simple:

class TestInitOrder {
  static {
    System.out.println(TestInitOrder.stat1);
    System.out.println(TestInitOrder.stat2);
    System.out.println(TestInitOrder.str);
    System.out.println(TestInitOrder.str2);

    str = "something";

    System.out.println(TestInitOrder.str);
    System.out.println(TestInitOrder.str2);
    System.out.println(TestInitOrder.lazy);
    System.out.println(TestInitOrder.second);
  }

  private static final int stat1 = 10;
  static final String str2 = "sdfff";
  static String str = "crap";
  private static int stat2 = 19;
  static final Second second = new Second();
  static final int lazy;

  static {
    lazy = 20;
  }

  static {
    System.out.println(TestInitOrder.str2);
    System.out.println(TestInitOrder.stat2);
    System.out.println(TestInitOrder.str);
    System.out.println(TestInitOrder.lazy);
    System.out.println(TestInitOrder.second);
  }

  public static void main(String args[]) {
  }

}

class Second {
  public Second() {
    System.out.println(TestInitOrder.second);
  }
}

According to Java Language Specification, from section 4.12.5:

Every variable in a program must have a value before its value is used:

  • Each class variable, instance variable, or array component is initialized with a default value when it is created

(The following lines from the specification specify the default value for all the types, basically some form of 0, such as 0, 0.0d, null, false, etc.)

So before the class is initialized (due to one of these reasons), the variables will hold an initial value.

According to the detailed initialization procedure (only the interesting steps are quoted here, and emphasis mine):

6. [...] Then, initialize the final class variables and fields of interfaces whose values are compile-time constant expressions (§8.3.2.1, §9.3.1, §13.4.9, §15.28).

[...]

9. 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.

Let us look at step 6, with the 4 final class variables: stat1, str2, second, lazy.

Since 10 is constant expression, and so is "sdfff", and due to the order of execution, it is not possible to observe the initial value for str2 and stat1. In order to make an observation, the earliest you can do is in step 9.

The case of second demonstrate that when the right hand side is not a compile-time constant expression, so its initial value is visible.

The case of lazy is different, since the assignment is done in static block, and hence happen in step 9 - so it is possible to observe its initial value. (Well, the compiler checks carefully that lazy is assigned exactly once).


After the initialization of final class variables with compile-time constant expression comes the execution of static blocks and the rest of the initializers.

As you can see from the example, the static blocks and initialization happens according to textual order - demonstrated with the use of str variable - it is first printed out as null, then something, then crap.

Tags:

Java

Static