Java Static Initialization Order

In what order do static/instance initializer blocks in Java run?

The static initializer for a class gets run when the class is first accessed, either to create an instance, or to access a static method or field.

So, for multiple classes, this totally depends on the code that's run to cause those classes to get loaded.

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

In Java, what is the order of initialization for those statements after main method

1) Block that does not have name like below is called "Instance Initializer" which only get called when new objects will be created its like DefaultConstructor or noArg Constructor.

{
add(11);
}

2) In above code you have Static Block (Which get called first at the Class Loading itself), Instance Initializer (Which get called while creating the object), Explicit DefaultConstructor (Which get called while creating the object but remember always Instance initializer takes priority) and last Main method.

3) Now lets analyze your code,

1st call:

static 
{
add(2); //print 2
}

2nd call:

static {
add(4); // print 4
}

3rd call:

static {
new Test1();
// Here Object is getting created so all Instance Initialzer will be called first in a sequential manner.
}

4th call:

{
add(6); // print 6
}

5th call:

{
add(8); // print 8
}

6th call:

{
add(11); // print 11
}

7th call : After Instance Initializer, Explicit Default Constructor will be called.

public Test1() {
add(5); // print 5
System.out.println("Constructor!"); // print Constructor!
}

8th call: Again the last Static block will be called.

static {
add(12); // print 12
}

9th call: Finally the main method will be called

public static void main(String[] args) {
System.out.println("Main method!"); // print Main method!
add(10); // print 10
}

Java Static Initialization Order

I think you're just missing section 12.4.2 of the JLS, which includes:

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.

The "in textual order" part is the important bit.

If you change m from being static variable to an instance variable, then the field won't be initialized by class initialization - it'll only be initialized by instance initialization (i.e. when an instance is constructed). At the moment, that'll cause a stack overflow - creating one instance requires creating another instance, which requires creating another instance, etc.

EDIT: Similarly section 12.5 specifies instance initialization, including these steps:

  • Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

  • Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

So that's why you're seeing "NON-STATIC BLOCK" before "MAIN CONSTRUCTOR".

Order of initialization of static variable in Java

It depends on when each class is first used.

From section 12.4.1 of the Java Language Specification:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.

  • T is a class and a static method declared by T is invoked.

  • A static field declared by T is assigned.

  • A static field declared by T is used and the field is not a constant variable (§4.12.4).

  • T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.

A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.

Section 12.4.2 of the JLS specifies the initialization procedure in detail.

To be honest, if your code requires one to be initialized before the other, despite having no obvious dependency, then you've got problems anyway.

Order of static initialization blocks

Static initializers are executed as soon as the class is loaded. The main method is called after the class has been loaded.

This section of the JLS discusses the sequence of events (12.1.3-4):

12.1.3. Initialize Test: Execute Initializers


In our continuing example, the Java Virtual Machine is still trying to execute the method main of class Test. This is permitted only if the class has been initialized (§12.4.1).

Initialization consists of execution of any class variable initializers and static initializers of the class Test, in textual order. But before Test can be initialized, its direct superclass must be initialized, as well as the direct superclass of its direct superclass, and so on, recursively. In the simplest case, Test has Object as its implicit direct superclass; if class Object has not yet been initialized, then it must be initialized before Test is initialized. Class Object has no superclass, so the recursion terminates here.


12.1.4. Invoke Test.main


Finally, after completion of the initialization for class Test (during which other consequential loading, linking, and initializing may have occurred), the method main of Test is invoked.

Java order of Initialization and Instantiation

It is important to distinguish between the initialization of a class, and initialization of an object.

Class Initialization

A class or interface is initialized upon first access, by assigning the compile time constant fields, then recursively initializing the superclass (if not already initialized), then processing the static initializers (which include the initializers for for the static fields that are not compile time constants).

As you have noticed, initialization of a class does not, by itself, trigger initialization of the interfaces it implements. Interfaces are therefore initialized when they are first accessed, typically by reading a field that is not a compile time constant. This access may occur during evaluation of an initializer, causing a recursive initialization.

It is also worth noting that initialization is not triggered by accessing fields that are compile time constants, as these are evaluated at compile time:

A reference to a field that is a constant variable (§4.12.4) must be resolved at compile time to the value V denoted by the constant variable's initializer.

If such a field is static, then no reference to the field should be present in the code in a binary file, including the class or interface which declared the field. Such a field must always appear to have been initialized (§12.4.2); the default initial value for the field (if different than V) must never be observed.

If such a field is non-static, then no reference to the field should be present in the code in a binary file, except in the class containing the field. (It will be a class rather than an interface, since an interface has only static fields.) The class should have code to set the field's value to V during instance creation (§12.5).

Object Initialization

An object is initialized whenever a new object is created, typically by evaluation of a class instance creation expression. This proceeds as follows:

  1. Assign the arguments for the constructor to newly created parameter variables for this constructor invocation.

  2. If this constructor begins with an explicit constructor invocation (§8.8.7.1) of another constructor in the same class (using this), then evaluate the arguments and process that constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason; otherwise, continue with step 5.

  3. This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super). Evaluate the arguments and process that superclass constructor invocation recursively using these same five steps. If that constructor invocation completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, continue with step 4.

  4. Execute the instance initializers and instance variable initializers for this class, assigning the values of instance variable initializers to the corresponding instance variables, in the left-to-right order in which they appear textually in the source code for the class. If execution of any of these initializers results in an exception, then no further initializers are processed and this procedure completes abruptly with that same exception. Otherwise, continue with step 5.

  5. Execute the rest of the body of this constructor. If that execution completes abruptly, then this procedure completes abruptly for the same reason. Otherwise, this procedure completes normally.

As we can see in step 3, the presence of an explicit call to the super constructor simply changes which super class constructor is invoked.



Related Topics



Leave a reply



Submit