Статический блок не вызывается

Кто может объяснить, что происходит?

public class MagicFinal {

    public static void main(String[] args) {
        System.out.println(A.s);
    }
}

class A {
    static {
        System.out.println("class has been loaded");
    }

    public static final String s = "final";

    public static final Integer i = 3;


}

Приставка:

окончательный

Что это? Я не понимаю, почему класс не был загружен, я знаю, что классы всегда загружаются при первом вызове. поле s в пуле строки, я вижу, что последний модификатор является магией.

Если я удалю окончательный модификатор (public static String s = "final") Я получу

Приставка:

класс был загружен

окончательный

Примечание: я изменил поле i: public static final int i = 3; и показать это в консоли. Я получил так же, как в строковой ситуации. Зачем?

2 ответа

Решение

"final" является строковым литералом и как таковое является константным выражением во время компиляции. Значение static final переменная, инициализированная константным выражением во время компиляции, напрямую жестко закодирована в классе, который ссылается на нее, и не делается ссылка на исходный класс. Поэтому инициализация исходного класса не происходит.

В качестве побочного момента, пожалуйста, обратите внимание на различие между загрузкой класса и инициализацией класса: только появление последнего точно определено JLS. Загрузка классов может произойти в любое время.

Это то, что написано в Спецификации языка Java {8.3.2.1 Инициализаторы для переменных класса}. Это должно ответить на ваш вопрос

Здесь есть одна тонкость: во время выполнения статические переменные, которые являются окончательными и инициализируются значениями констант во время компиляции, инициализируются первыми. Это также относится к таким полям в интерфейсах (§9.3.1). Эти переменные являются "константами", которые никогда не будут иметь своих начальных значений по умолчанию (§4.12.5), даже в хитрых программах. См. §12.4.2 и §13.4.9 для дальнейшего обсуждения.

Другие вопросы по тегам