Reputation: 97
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
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
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
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