Почему компилятор Java сообщает только об одном виде ошибки одновременно? - PullRequest
3 голосов
/ 27 сентября 2011

У меня есть фрагмент

class T{
    int y;
    public static void main(String... s){
        int x;
        System.out.println(x);
        System.out.println(y);
    }
}

Здесь есть две ошибки, но при компиляции почему отображается только одна ошибка?

Показанная ошибка:

non-static variable y cannot be referenced from a static context
    System.out.println(y);
                       ^

А как же ошибка

variable x might not have been initialized
    System.out.println(x);
                       ^

Ответы [ 4 ]

12 голосов
/ 27 сентября 2011

Компилятор Java компилирует ваш код за несколько проходов . На каждом проходе обнаруживаются определенные виды ошибок. В вашем примере javac не смотрит, может ли x быть инициализирован или нет, пока остальная часть кода фактически не пройдет предыдущий проход компилятора.

5 голосов
/ 27 сентября 2011

@ Грег Хьюгилл прибил его.

В частности, проверки для инициализируемых переменных, объявляемых исключений, недоступного кода и некоторых других вещей происходят на более позднем этапе.Этот проход не выполняется, если в предыдущих проходах были ошибки.

И для этого есть веская причина.Предыдущие этапы создают декорированное дерево разбора, которое представляет программу в том виде, в котором ее понимает компилятор.Если ранее были ошибки, это дерево не будет точным представлением программы, как ее понимает разработчик.(Этого не может быть!).Если компилятор затем продолжит выполнение более позднего прохода, чтобы произвести больше сообщений об ошибках, есть вероятность, что многие из этих сообщений об ошибках будут вводить в заблуждение артефакты неправильного дерева разбора.Это только сбило бы с толку разработчика.

Во всяком случае, так работает большинство компиляторов для большинства языков программирования.Исправление некоторых ошибок компиляции может привести к появлению других (ранее не сообщенных) ошибок.

2 голосов
/ 27 сентября 2011

Книга Дракона («Компиляторы: принципы, методы и инструменты» Ахо, Сетхи и Уллмана) описывает несколько методов, которые авторы компиляторов могут использовать для улучшения обнаружения ошибок и создания отчетов при вводе данных.файлы, которые не соответствуют спецификации языка.

Некоторые из методов, которые они дают:

  • Восстановление в режиме паники: пропускайте все входные токены во входном потоке, пока вы ненашли «синхронизирующий токен» - например, операторы ;, } или end и терминаторы или разделители блоков, или do, while, for, function и т. д.которые могут показать предполагаемые запуски новых блоков кода и т. д. Надеемся, что ввод с этой точки будет иметь смысл для анализа и возврата полезных сообщений об ошибках.

  • Восстановление уровня фразы: угадайте, чтофраза может означать: вставлять точки с запятой, заменять запятые на точки с запятой, вставлять = операторы присваивания и т. д., и надеяться, что результат имеет достаточный смысл для парсингаe и возвращает полезные сообщения об ошибках.

  • Произведения ошибок: в дополнение к "законным" производствам, которые распознают допустимые операторы грамматики, есть "производства ошибок", которые распознают ошибки на языке, будет против грамматики, но что авторы компилятора признают очень вероятные ошибки.Сообщения об ошибках для них могут быть очень хорошими, но могут резко увеличить размер анализатора для оптимизации ошибок ввода (что должно быть исключением, а не общим случаем).

  • Глобальное исправление: попытайтесь внести минимальные изменения во входную строку, чтобы попытаться вернуть ее в программу, которую можно проанализировать.Так как исправления могут быть внесены различными способами (вставка, изменение и удаление любого количества символов), попробуйте сгенерировать их все и обнаружить изменение «наименьшей стоимости», которое делает программу достаточно хорошо анализируемой для продолжения анализа.

Эти параметры представлены в главе о разборе грамматики (стр. 161 в моем издании) - очевидно, некоторые ошибки обнаруживаются только после того, как входной файл был проанализирован, но начинает преобразовываться восновные блоки для оптимизации и генерации кода.Любые ошибки, возникающие на более ранних синтаксических уровнях, не позволят типичному компилятору запускать фазы оптимизации и генерации кода, и любые ошибки, которые могут быть обнаружены на этих этапах, должны ждать фиксированного ввода, прежде чем они смогут быть запущены.

Я настоятельно рекомендую найти копию Книги Дракона, она даст вам некоторое сочувствие и, надеюсь, вновь обретенное уважение к нашим дружелюбным авторам компиляторов.

1 голос
/ 27 сентября 2011

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

...