Static & Instance Initializers

Code block used to run arbitrary code during class or instance initialization.

Static and Instance initializers (sometimes called initializer blocks) are used to run arbitrary code during initialization of a type or object. They both can be located directly within a class, normal interface, or enum.

Syntax

Initializer Blocks have the following forms:

1 static { statements }
2 { statements }

where...

statements is a sequence of statements, (just like in the body of any other code block). The statements can be separated by whitespace. (For more details, see blocks.)

Syntax Elements

1 A static initializer.

2 An instance initializer.

Behavior

Initializers are used to run arbitrary code during initialization of a class or object. They provide a means of executing statements and expressions beyond what can be executed through the variable initializer of a static or instance field. An initializer executes its body statements from top to bottom, in order, just like a normal code block.

Ordering & Interleaving

The variable initializers in instance field declarations and the instance initializer blocks, contained within a type, collectively make up the initialization code that gets executed when an instance of that type is created. (See the Instance Initializer Code example below for details.) Similarly, the variable initializers of static fields and the static initializer blocks collectively make up the initialization code that is executed when the type is loaded. (See the Static Initializer Code example below for details.) In either case, initialization code is always executed in the same textual order as it is written throughout the class. Thereby, it is said that such initialization code is ordered. Note that other code contained within a type, (e.g. methods, constructors, inner types), is not subject to initialization code ordering.

Initializer code is executed in the order of its textual appearance. For example, consider the following class:
public class Test {
	int x = 10;
	{
		System.out.println("x's initial value: " + x);// Prints 10.
	}
	int y = x++; // Sets y to 10 and increments x to 11.
	{
		System.out.println("x's new value: " + x); // Prints 11. The change inside y's variable initializer above is reflected.
		System.out.println("y's value: " + y); // Prints 10.
	}
}

If a new Test(); object is created, the above code will print the following:

x's initial value: 10
x's new value: 11
y's value: 10

Constraints

Placement

Both static and instance initializers are permitted only in the body of a type. static initializers may be present in any static class or in an enum (which is implicitly static). Specifically, static initializers may be present in:

Instance initializers may be placed in any class body, (including inner, local, and anonymous classes), or in enums after the enum constant header.

Field Reference

Both static and instance initializers are disallowed from referencing a field if the following are true:

  1. The field is declared textually after the occurrence of the initializer,
  2. the field is of the same type as the initializer (static or instance), and
  3. the reference is through a simple name such as x. A simple name is:
    • for static fields, the field's unqualified name (e.g. x instead of ClassName.x).
    • for instance fields, the field's unqalified name (e.g. x) or the latter accessed directly through this, (e.g. this.x).

This disallows initializers from directly referring to fields in a forward-reference fashion.

final Fields

There are additional constraints that apply to both types of initializers and their respective types of fields if the fields are marked final, regarding...

Initialization of final Fields

Such initialization must be performed through simple reference; it is always a compile-time error to attempt to assign to a final field other than through a simple reference.

Reference of Uninitialized final Fields

It is a compile time error if an initializer block attempts to refer to a final field through simple reference, before its initialization, unless that reference is as the left-hand side of an assignment. final fields must be initialized (via simple reference) before they can be referenced in ways other than assignment (by simple reference).

static Initializers

static initializers may not directly refer to instance members, as there is no implicitly accessible state available for static code. References to instance members must be qualified with an expression.

Examples

Simple Example

public class Dog {
	String q = "ABC"; // "Conventional" initialization code: give field a value.
	{
		System.out.println("First Statement");
		System.out.println("Second Statement");
	}
}

Simply creating a new Dog(); will cause the initializer block to run, resulting in the output:

First Statement
Second Statement

Order of Execution

class Test {
	{
		System.out.println("Point 1: " + ((Test) this).x); // At this point, x has not been declared, and so has value 0.
		// x++;			// x is not yet declared.
		// this.x++;	// x is not yet declared.
		((Test) this).x++; // x is now 1.
		System.out.println("Point 2: " + ((Test) this).x);
	}
	int x = 5; // x is set to 5.
	{
		System.out.println("Point 3: " + x);
		// Increment x 3 times:
		x++;
		this.x++;
		((Test) this).x++; // x is now 8
		System.out.println("Point 4: " + x);
	}
}

This code prints the following:

Point 1: 0
Point 2: 1
Point 3: 5
Point 4: 8

Mixing static and Instance Initializers

Instance initializer code can access static fields:

public class Example {
	static int count;
	String str;
	{
		str = "Item #" + count++;
	}

	public static void main(String[] args) {
		System.out.println(new Example().str); // Create one example object.
		System.out.println(new Example().str); // Create another.
		System.out.println(new Example().str);
		
		Example nextExample = new Example(), lastExample = new Example();
		System.out.println();
		System.out.println("Last two Example objects:");
		System.out.println(nextExample.str);
		System.out.println(lastExample.str);
	}
}

Output:

Item #0
Item #1
Item #2

Last two Example objects:
Item #3
Item #4

Initializers Interleaved With Members

public class C {
	static {
		System.out.println("Initializer 1 (Static)");
	}
	{
		System.out.println("Initializer 2 (Instance)");
	}
	
	C() {
		System.out.println("Constructor");
	}
	
	static {
		System.out.println("Initializer 3 (Static)");
	}
	{
		System.out.println("Initializer 4 (Instance)");
	}
	
	public static void main(String[] args) {
		System.out.println("Main method started.");
		new C();
	}
}

Output:

Initializer 1 (Static)
Initializer 3 (Static)
Main method started.
Initializer 2 (Instance)
Initializer 4 (Instance)
Constructor

Instance Initializer Code

Add example code

Static Initializer Code

Add example code

Notes

  1. It is possible to declare a final instance field without initializer blocks or a constructor, even when that field is declared without a variable initializer:
    public class InitializerTest {
    	final int x;
    	final int y;
    	final int z;
    	final double test = x = y = z = 10;
    }

    In this example, the three int variables are each set to 10 and the variable test is set to 10.0. This is also possible for static fields.

    public class InitializerTest {
    	static final int x;
    	static final int y;
    	static final int z;
    	static final double test = x = y = z = 10;
    }
  2. It is possible to access a field in code that has not yet been declared in multiple ways. For example, by using a non-simple name:
    public class Test {
    	static final int x = Test.y;
    	static final int y = Test.x;
    }

    As with other fields, the default value of y, (which is what Test.y evaluates to in x's variable initializer), is 0, so both x and y are initialized to the value 0.

  3. It is possible for instance initializer code to be executed before static initializer code completes, particularly in the case that static initializer code attempts to create an object of the class currently being initialized:
    class Test {
    	// Instance initializer code
    	{
    		System.out.println(x);
    	}
    	
    	// Static initializer code
    	static int x;
    	static {
    		new Test(); // Create new Test before static initialization has completed. This causes the instance initializer to be run.
    		// The object instantiation prints 0, since x has not been assigned to yet.
    		
    		x = 10000;
    	}
    }

    Output:

    0
  4. It is possible to run code before the main(String[]) method begins by including such code in a static initializer block in the class containing the main(String[]) method:
    public class Test {
    	private static int x;
    	static {
    		Scanner s = new Scanner(System.in);
    		System.out.print("Please enter a number: ");
    		x = s.nextInt();
    	}
    	
    	public static void main(String[] args) {
    		System.out.println("You entered " + x + " before the main method was called.");
    	}
    }

    Calling this code and providing the command-line input:

    14
    

    will print the output:

    You entered 14 before the main method was called.
  5. It is possible to include a static initializer inside an interface (including @interfaces) indirectly, by declaring a class or enum within the interface and including the static initializer inside that.