What Is an Initialization Block

What is an initialization block?

First of all, there are two types of initialization blocks:

  • instance initialization blocks, and
  • static initialization blocks.

This code should illustrate the use of them and in which order they are executed:

public class Test {

static int staticVariable;
int nonStaticVariable;

// Static initialization block:
// Runs once (when the class is initialized)
static {
System.out.println("Static initalization.");
staticVariable = 5;
}

// Instance initialization block:
// Runs each time you instantiate an object
{
System.out.println("Instance initialization.");
nonStaticVariable = 7;
}

public Test() {
System.out.println("Constructor.");
}

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

Prints:

Static initalization.
Instance initialization.
Constructor.
Instance initialization.
Constructor.

Instance itialization blocks are useful if you want to have some code run regardless of which constructor is used or if you want to do some instance initialization for anonymous classes.

Need for initialization block in Java

There are two types of initializer blocks.
You have a static initializer block which runs on creation of class. Its syntax is

static {
//stuff here
}

The other one is instance initialization block which runs when you instantiate an object. Its syntax is

{
//stuff here
}

If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate. Instance variables can be initialized in constructors, where error handling or other logic can be used. To provide the same capability for class variables, the Java programming language includes static initialization blocks.

This is to answer your question on when you should use them. You basically use them to initialize a variable with some kind of specific logic. It's from the official Oracle documentation.

Static Initialization Blocks

The non-static block:

{
// Do Something...
}

Gets called every time an instance of the class is constructed. The static block only gets called once, when the class itself is initialized, no matter how many objects of that type you create.

Example:

public class Test {

static{
System.out.println("Static");
}

{
System.out.println("Non-static block");
}

public static void main(String[] args) {
Test t = new Test();
Test t2 = new Test();
}
}

This prints:

Static
Non-static block
Non-static block

Initializer block inside the main method?

To summarize the comments for others who stumble across this question:
the {} is a block that defines scope. In this particular example the value of j inside the block will be 3. However outside the block would be zero. That would cause different results of the additions.

Also note that this statement System.out.println("i + j is " + i + j); would just print

"i + j is 23"

and not

"i + j is 5"

This is because the + operator would just convert all the ints to their string representation and append them.
If you do want to have the sum it statement should actually be:
System.out.println("i + j is " + (i + j));

Why can my instance initializer block reference a field before it is declared?

From docs:

The Java compiler copies initializer blocks into every constructor.
Therefore, this approach can be used to share a block of code between
multiple constructors.

The above statement is slightly misleading, because if we follow the explanation of the above doc we can rewrite the original code like this:

public class WrongVersionOfWhyIsThisOk {

int a = 10;

public WhyIsThisOk (){
a = 5;
}

public static void main(String[] args){
WrongVersionOfWhyIsThisOk why = new WrongVersionOfWhyIsThisOk ();
System.out.println(why.a);
}
}

But running WrongVersionOfWhyIsThisOk will produce 5 instead of 10 that original code produces.

But in reality it is both the initializer block and variable assignment are copied into constructor:

public class RightVersionOfWhyIsThisOk {

int a;

public RightVersionOfWhyIsThisOk (){
a = 5;
a = 10;
}

public static void main(String[] args){
RightVersionOfWhyIsThisOk why = new RightVersionOfWhyIsThisOk ();
System.out.println(why.a);
}
}

Update:

Here is the doc describing in detail the initialization order and constructor invocation:

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.

Examples of why we need initialization blocks

why we need initialization blocks

For instance initialization blocks, I can only think on two cases:

  1. When creating an anonymous class:

    Runnable runnable = new Runnable() {
    int x;
    //initialization block here
    {
    //IMO this is such odd design, it would be better to not
    //create this as an anonymous class
    x = outerClassInstance.someMethod();
    }
    @Override
    public void run() {
    //write the logic here...
    }
    };
  2. When using double brace initialization (if the class is not marked final):

    List<String> stringList = new ArrayList<>() {
    {
    add("Hello");
    add("world");
    }
    };
    System.out.println(stringlist);
    //prints [Hello, world]

For static initialization blocks, there are two cases:

  1. When defining the data for a static field. This is covered in @ChrisThompson's answer.

  2. When initializing a constant (static final) field from an external source, like the result of some computation.

    class Foo {
    public static final boolean DEBUG;
    static {
    DEBUG = getDebugMode();
    }
    private static boolean getDebugMode() {
    //code to open a properties file, read the DEBUG property
    //and return the value
    }
    }

Static and Non-Static initialization blocks in Java

Non-static initialization blocks will be called on instance creation.

You never create a new instance, so the block is not executed.

When are initializer blocks used in java?

A common use for this is the static initializer block:

class A {
static boolean verbose;
final int x;
final int y;
final String n;

static {
verbose = doSomethingToGetThisValue();
}

public A(String name ) {

/* etc... etc */

This is useful because your static variables might be used by a static method before an instance of the class is ever created (and therefore before your constructor is ever called).

See also this SO answer.



Related Topics



Leave a reply



Submit