Nitesh
Nitesh

Reputation: 97

Order of excecution, static blocks

I have following scenario package com.example.test;

public class StaticTest {

    public static final String STATIC_VAR="Static Var";

    static{
        System.out.println("Static Block Called....");
    }
public static void init(){}
}

package com.example.test;

public class MainClass {
    public static void main(String[] args) {
        System.out.println("Test static initialization");
        String staticvar =StaticTest.STATIC_VAR;
        System.out.println("Referred static variable--> "+ staticvar);
        System.out.println("Calling static method");
        StaticTest.init();
        System.out.println("Static method invoked");
    }

}

The output I am getting is

Test static initialization
Referred static variable--> Static Var
Calling static method
**Static Block Called....**
Static method invoked

And output I was expecting was

Test static initialization
**Static Block Called....**
Referred static variable--> Static Var
Calling static method
Static method invoked

I was thinking that as soon as I refer static variable static block will get executed.

any explanation?

Upvotes: 1

Views: 122

Answers (3)

Andreas Fester
Andreas Fester

Reputation: 36649

The primary reason is that you declared STATIC_VAR as constant value, which will be inlined by the compiler instead of being referenced. Change the code to

public static /*final*/ String STATIC_VAR="Static Var";

and you will get the behaviour you expect.

See §12.4.1. When Initialization Occurs 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:

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

See the other answers on inlining of constant values for the technical background.

Upvotes: 0

David
David

Reputation: 20073

String staticvar =StaticTest.STATIC_VAR; 

does not load the class StaticTest. Instead, the compiler inlines the value of the constant into MainClass. So at runtime, this code will be executed:

String staticvar = "Static Var"; 

The JLS calls this a "constant":

A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.

which means that StaticTest.init(); is the first time when the VM has to actually load the class. This causes the execution of the static block.

Upvotes: 3

Boris the Spider
Boris the Spider

Reputation: 61198

Because the variable is public static final it is being inlined by the compiler.

All references to it are being replaced by the actual value as it cannot change, this is known as a Compile Time Constant.

Your code is essentially being compiled to:

System.out.println("Test static initialization");
String staticvar = "Static Var";

If you assign the value to the return value of a method -

public static final String STATIC_VAR=getStaticVar();
private static String getStaticVar() {
    return "Static Var";
}

You will get the result you expect.

There is a good SO answer the explains inlining and the guarantees given by the JLS on compile time constants.

Upvotes: 3

Related Questions