Как ссылка на переменную, объявленную ПОСЛЕ метода, работает в Java?

#java #compiler-construction

#java #построение компилятора

Вопрос:

После некоторого времени, проведенного с использованием Java, я всегда разрабатывал свой класс, следуя этому порядку: объявление переменных, конструктора, а затем методов. И я никогда не думал об этом, пока не наткнулся на код, который отлично компилируется:

 public class Main {

int m1(){
    return   i;
}

int i=10;

}
 

Мой вопрос в том, как это работает? То есть, когда компилятор начинает компилировать этот код, он должен начинаться сверху вниз, верно? Итак, как он узнает, что variable i означает и каково его значение? «Он не может заглядывать в будущее», чтобы сказать это глупо.

Может кто-нибудь сказать мне, как это вообще работает? Я только предполагаю, что компилятор сначала компилирует переменные, а затем конструктор / методы (независимо от моего порядка исходного кода). Но я не встречал никаких ссылок / документов на это, поэтому не хочу делать слепых предположений.

Комментарии:

1. Нет, он не может заглядывать в будущее. Но он может запомнить тот факт, что он видел что-то вызываемое i , сделать предположение, что оно будет определено позже, а затем выдать ошибку позже, если это предположение окажется неверным.

2. Вы также, похоже, работаете в предположении, что все компиляторы являются однопроходными компиляторами. Они не

3. Я уверен, что об этом недавно спрашивали и указывали на дубликат. Однако, похоже, я не могу ее найти.

Ответ №1:

Это работает, потому что компиляция выполняется в несколько этапов.

Одним из первых шагов является синтаксический анализ. Когда компилятор анализирует пример кода, он «отмечает», что используется идентификатор i и есть объявление переменной, у которой есть имя i . На основе этой информации (и набора правил) компилятор сопоставляет объявления идентификаторов и способы использования идентификаторов (и, например, создает таблицу символов).

Проверка того, имеет ли идентификатор правильный тип для использования, называется проверкой типа и выполняется на более позднем этапе.

Итак, к тому времени, когда компилятор «задает» вопросы типа «Что означает indentifier i ?», У него уже есть ответ на этапе синтаксического анализа.

Определить значение переменной может быть невозможно до времени выполнения (например, если значение вводится пользователем). Но если значение может быть определено во время компиляции, его можно использовать для оптимизации, такой как постоянное распространение, что является одним из более поздних этапов процесса компиляции.