Why does .class not invoke the static block in a Class?

This is the code I have:

public class StupidClass {
    static {
        System.out.println("Stupid class loaded!");
    }
}

And the tests I have, which I run separately.

import org.junit.Test;

public class StupidTest {
    @Test
    public void foo() throws ClassNotFoundException {
        final Class<?> stupidClass = Class.forName("StupidClass");
        System.out.println(stupidClass.getSimpleName());
    }

    @Test
    public void bar() throws ClassNotFoundException {
        final Class<StupidClass> stupidClassClass = StupidClass.class;
        System.out.println(stupidClassClass.getSimpleName());
    }
}

When I run test foo I will see:

Stupid class loaded!
StupidClass

But when I run the test bar all I see is:

StupidClass

Quoting from this page..

Class objects are constructed automatically by the Java Virtual Machine as classes are loaded and by calls to the defineClass method in the class loader.

So my understanding is, in test bar, Stupid class is loaded, otherwise I would have seen a null I guess? So Class object is created because class itself is loaded..

And now quoting from this page

Static initialization blocks are run when the JVM (class loader - to be specific) loads StaticClass (which occurs the first time it is referenced in code).

So I am expecting to see the "Stupid class loaded!" text in test bar as well, but I am not.

Also quoting from Thinking in Java

Each of the classes Candy, Gum, and Cookie has a static clause that is executed as the class is loaded for the first time.

which is not very accurate it seems..

What am I missing?

Answers 1

  • Static initialization blocks are run when the JVM (class loader - to be specific) loads StaticClass (which occurs the first time it is referenced in code).

    The above quote is plain wrong, but it is just one instance of a very widespread misconception.

    1. Class is not initialized when it's being loaded, but when a static class member is first referenced. This is precisely governed by the specification.

    2. Class loading does not occur when the class is first referenced, but at an implementation-dependent point.

    3. The last moment when the class must be loaded is when the class is referenced, which is not the same as referencing a class member.

    Class.forName initializes the class by default, but you have the choice of calling an overload that takes a boolean initialize and supplying false. You'll get the class loaded without initializing.


Sorry, you do not have a permission to answer to this question.