Difference Between a Static and a Non-Static Initialization Code Block

What is the difference between a static and a non-static initialization code block

The code block with the static modifier signifies a class initializer; without the static modifier the code block is an instance initializer.

Class initializers are executed in the order they are defined (top down, just like simple variable initializers) when the class is loaded (actually, when it's resolved, but that's a technicality).

Instance initializers are executed in the order defined when the class is instantiated, immediately before the constructor code is executed, immediately after the invocation of the super constructor.

If you remove static from int a, it becomes an instance variable, which you are not able to access from the static initializer block. This will fail to compile with the error "non-static variable a cannot be referenced from a static context".

If you also remove static from the initializer block, it then becomes an instance initializer and so int a is initialized at construction.

Difference between the static initializer block and regular static initialization

For your example, there is no difference. But as you can see,

public static String myString = "Hello World!";

can only accept an expression to initialize the variable. However, in a static initializer (JLS 8.7), any number of statements may be executed. E.g. it's possible to do this:

static
{
myString = "Hello";
myString += " ";
myString += "World";
}

For your example, there's obviously no need to do that, but it's possible for the initialization of a variable to take more than an expression, perhaps many statements, so Java made static initializers.

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.

What is difference between static block and static field?

Both code fragments do the same thing, but most people will find the compact version easier to read.

There are things you cannot do in the single line assignment version, such as handling exceptions. In those cases you have to use an initializer block.

A third way would be to move the initializer code into a (static) method.

private static final Pattern pattern = doSomethingReallyComplexHere();

Static block vs. initializer block in Java?

They're for two very different purposes:

  • The static initializer block will be called on loading of the class, and will have no access to instance variables or methods. As per @Prahalad Deshpande's comment, it is often used to create static variables.
  • The non-static initializer block on the other hand is created on object construction only, will have access to instance variables and methods, and (as per the important correction suggested by @EJP) will be called at the beginning of the constructor, after the super constructor has been called (either explicitly or implicitly) and before any other subsequent constructor code is called. I've seen it used when a class has multiple constructors and needs the same initialization code called for all constructors. Just as with constructors, you should avoid calling non-final methods in this block.

Note that this question has been answered many times in stackoverflow and you would do well to search and review the similar questions and their answers. For example: static-initialization-blocks

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

What is the alternative to a non-static initialization block?

First of all, it doesn't make sense to initialize test to a new String() there, since the initialization block immediately assigns it to something else. Anyways...

One alternative is initializing at the declaration:

public class BlockTest {
String test = "testString";
}

Another is in the constructor:

public class BlockTest {
String test;
public BlockTest () {
test = "testString";
}
}

Those are the two main, common options.

There are two main uses for an initialization block. The first is for anonymous classes that have to perform some logic during initialization:

new BaseClass () {
List<String> strings = new ArrayList<String>();
{
strings.add("first");
strings.add("second");
}
}

The second is for common initialization that must happen before every constructor:

public class MediocreExample {
List<String> strings = new ArrayList<String>();
{
strings.add("first");
strings.add("second");
}
public MediocreExample () {
...
}
public MediocreExample (int parameter) {
...
}
}

However, in both cases there are alternatives that do not use the initialization block:

new BaseClass () {
List<String> strings = createInitialList();
private List<String> createInitialList () {
List<String> a = new ArrayList<String>();
a.add("first");
a.add("second");
return a;
}
}

And:

public class MediocreExample {
List<String> strings;
private void initialize () {
strings = new List<String>();
strings.add("first");
strings.add("second");
}
public MediocreExample () {
initialize();
...
}
public MediocreExample (int parameter) {
initialize();
...
}
}

There are many ways to do these things, use the way that is most appropriate and provides the clearest and most easily maintainable code.



Related Topics



Leave a reply



Submit