1

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?

Nitesh
  • 97
  • 1
  • 10
  • 1
    Please see [Java static class initialization](http://stackoverflow.com/questions/3499214/java-static-class-initialization) and [What order are static blocks and static variables in a class executed?](http://stackoverflow.com/questions/12448465/in-what-order-are-static-blocks-and-static-variables-in-a-class-executed). – Charlee Chitsuk Apr 12 '13 at 07:55

3 Answers3

3
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.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
David
  • 19,577
  • 28
  • 108
  • 128
3

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.

Community
  • 1
  • 1
Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
0

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.

Andreas Fester
  • 36,091
  • 7
  • 95
  • 123