Почему.класс не вызывает статический блок в классе?


это код, который у меня есть:

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

и тесты у меня есть, которые я запускаю отдельно.

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());
    }
}

когда я запускаю тест фу Я вижу:

Stupid class loaded!
StupidClass

но когда я запускаю тест бар все что я вижу это:

StupidClass

цитирую этой

2 68

2 ответа:

статические блоки инициализации запускаются, когда JVM (загрузчик классов - чтобы быть конкретным) загружает StaticClass (который происходит в первый раз, когда на него ссылаются в коде).

приведенная выше цитата явно неверна, но это всего лишь один пример очень распространенного заблуждения.

  1. класс не инициализируется когда он загружается, но когда статический класс это первая ссылка. Это точно регулируется кстати спецификация.

  2. загрузка класс не происходит при первой ссылке на класс, но в точке, зависящей от реализации.

  3. последний момент, когда класс должен быть загружен, когда класс ссылается, что не то же самое как ссылка на класс .

Class.forName инициализирует класс по умолчанию, но у вас есть выбор вызова перегрузки, которая принимает boolean initialize и поставляя false. Вы получите класс загружается без инициализации.

загрузка и инициализация класса-это 2 разные вещи. Класс может быть загружен, но не инициализирован до тех пор, пока это действительно необходимо. Статические инициализаторы запускаются только тогда, когда класс инициализируется не загружается, "инициализируется"

в первом случае вы загружаете и инициализируете класс при использовании class.forName(), вот почему статические инициализаторы запускаются и, следовательно, вы видите "Stupid class loaded!" как выходной . Во втором случае вы просто назначаете ссылку на класс класс загружается (используйте java-verbose: class, чтобы увидеть, какие классы загружаются), но вы на самом деле не инициализируете его (или, точнее, не делаете ничего, что заставляет инициализаторы работать). Таким образом, вы не видите выход как Stupid class loaded!. Попробуйте сделать что-то вроде вызова newInstance() в классе он должен принудительно инициализировать класс, и вы должны увидеть Stupid class loaded!

мой код :

public class CheckPalindrome {

    public static void main(String[] args) {
        Class<Test> t = Test.class;
    }

}
// class being loaded
class Test {
    static {
        System.out.println("aaa");
    }
}

классы, которые загружаются

...
[Loaded Test from file:/Workspaces/SampleTest/Java8/bin/]
...

^ - это показывает, что класс загружен, но не инициализирован.