5

I am confused with the output of the below code. I know first static block gets executed after class loading but why is my class Test6 not getting loaded. Can someone please clarify.

package com.vikash.General;

public class Test5 {

    public static void main(String[] args) {
        System.out.println(Test6.FOO);
    }
    static {
        System.out.println("Initializing B");
    }
}
class Test6{

    public static final String FOO = "foo";
    static {
        System.out.println("Initializing A");
    }
}
Eashi
  • 347
  • 1
  • 9

4 Answers4

9

Test6.FOO refers to Test6, but the field is a public static final String initialized from a compile-time constant, so it will be inlined by the compiler, and Test6 does not need to be loaded at all.

Community
  • 1
  • 1
Thilo
  • 257,207
  • 101
  • 511
  • 656
  • Indeed. When removing the `final` the static initalizer will be invoked – Clayn May 19 '16 at 09:54
  • @Thilo Can you explain "it will be inlined by the compiler". I cannot understand. This is new to me – mubeen May 19 '16 at 10:00
  • 1
    In effect, the code becomes `System.out.println("foo")`. The compiler replaces the reference to the field with the String literal. At runtime, `Test6` is not needed for this line of code. – Thilo May 19 '16 at 10:01
  • 2
    This can lead to problems if you later change `Test6.FOO` to another string. `Test5` will still print the old version (unless you also recompile `Test5`). – Thilo May 19 '16 at 10:02
2

It seems to be because the compiler is inlining the reference to the string literal "foo", so the JRE doesn't actually bother loading Test6 to get it.

If you make a change such as:

public static final String FOO = new String("foo");

then the class Test6 does get loaded (and its static block gets executed).

khelwood
  • 55,782
  • 14
  • 81
  • 108
  • It also works with a literal when `FOO` is not final. But in case it should be, your solution works as well. – Clayn May 19 '16 at 09:55
0

Use a class loader you will get the desired output

Class.forName("<package>.Test6");
Helios
  • 851
  • 2
  • 7
  • 22
-3

Test6 is not initialized at all.

the foo is static, which means it can be used before class is intitialized and after a class is load.

sotondolphin
  • 223
  • 1
  • 10
  • 3
    I don´t know if i understand this answer completly, but i am pretty sure it´s wrong and doesn´t answer the question. – SomeJavaGuy May 19 '16 at 09:58
  • because it doesn´t explain why `Test6` is not loaded. It is just follwed by a confusing explenation of `foo is static`, which at this point is unrelated to the behavior. Actually this is the question, despite `foo` beeing `static`, why doesn´t it load `Test6` and hence call the `static initializer block` – SomeJavaGuy May 19 '16 at 10:00
  • I told you it's loaded into JVM but not initialized. – sotondolphin May 19 '16 at 10:01
  • 1
    So you are telling foo can be used before class is initialized and after a class load but not in between? I am really confused what you want to tell us and which class do you refer to. – tak3shi May 19 '16 at 10:07