2013-09-24 3 views
32

Кто может объяснить, что происходит?Статический блок не называется

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; и показать его в conso ле. Я получил то же самое, что и в ситуации String. Зачем?

ответ

46

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

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

+1

Хорошо, спасибо много! Как насчет int ?? открытый статический окончательный int i = 3; // не загружен класс записи public static final Integer i = 3; // загружен класс записи – idmitriev

+4

Прочтите определение выражения константы времени компиляции, к которому я связался в своем ответе. 'int 'является примитивным значением,' String' является единственным частным случаем ссылочного значения, которое может быть использовано в константном выражении, а 'Integer' не является ни тем, ни другим. –

+0

@marko - Вы говорите мне, что класс A вообще не загружается? или это случай ленивой инициализации ??? – TheLostMind

3

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

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

+0

Похоже, вы имеете в виду * Спецификация языка Java, третье издание *. Такого абзаца нет в * Java® Language Specification Java SE 7 Edition *. – johnchen902

+0

Да. Это верно. Я смотрел старое издание, но это утверждение справедливо и для JLS 7. Ниже строки взяты из JLS7 Во время выполнения сначала инициализируются статические поля, которые являются окончательными и которые инициализируются постоянными выражениями (§15.28) (§12.4.2). Это также относится к таким полям в интерфейсах (§9.3.1). Эти поля являются «константами», которые никогда не будут наблюдаться до , имеют начальные значения по умолчанию (§4.12.5) даже при использовании коварных программ (§13.4.9). –

Смежные вопросы