Почему вы можете получить доступ к статическому полю до его определения с помощью метода в Java? - программирование
Подтвердить что ты не робот

Почему вы можете получить доступ к статическому полю до его определения с помощью метода в Java?

У меня возникла интересная вещь:

static {
    System.out.println(test);     // error cannot reference a field before it is defined
    System.out.println(cheat());  // OK! 
}

private static boolean cheat() {
    return test;
}

private static boolean test = true;

public static void main(String args[]) {}

Первый способ неправильный, и ваш компилятор и IDE скажут вам это неправильно. Во втором случае обман в порядке, но на самом деле по умолчанию поле test равно false. Использование Sun JDK 6.

4b9b3361

Ответ 1

Это определено в JLS 8.3.2.3. В частности:

Объявление элемента должно появляться текстовым образом перед его использованием [...], если использование происходит в статическом инициализаторе [...] C.

Когда вы вызываете cheat(), вы обходите это правило. Это фактически пятый пример в список примеров этого раздела.

Обратите внимание, что cheat() возвращает false в статическом блоке инициализатора, потому что test еще не инициализирован.

Ответ 2

Так как загрузка классов работает в следующем порядке:

  • Loads Определение класса (методы, подписи)
  • Выделяет память для ссылок на статические переменные (для test) - еще не инициализируется
  • Выполняет инициализаторы static (для переменных) и блоки static - для того, чтобы они были определены

Итак, к тому времени, когда вы достигнете блока static, у вас есть определение метода готово, но у него нет готовой переменной. С cheat() вы действительно читаете неинициализированное значение.

Ответ 3

Это общие шаги, по которым происходит загрузка классов.

  • Загрузка - загрузка класса в память
  • Проверка - проверяет двоичное представление класса e правильно
  • Подготовка - создайте статические поля для класса и инициализируйте эти поля стандартными значениями по умолчанию.
  • Инициализация - вызовет статические инициализаторы и инициализаторы для статических полей

После подготовки ваш тест будет ложным. Затем, прежде чем назначить статическую переменную в значение true, ваш статический блок будет выполнен. Вот почему вы получаете false.

Попробуйте сделать свою статическую переменную окончательной. В этом случае вы получите правду. Это связано с тем, что ваш компилятор будет вставлять значение в байт-код (поскольку поле является окончательным) в качестве части оптимизации