Перейти к содержимому
Теория · Первая программа · урок 5 из 8

Ошибки компиляции

Компилятор — строгий корректор. Прежде чем партитура попадёт к оркестру, он проверяет каждую её строку. Найдя нарушение, корректор возвращает текст с пометками на полях, и концерт не начинается.

Вот программа, в которой забыта одна точка с запятой:

JAVA
public class Main {
    public static void main(String[] args) {
        System.out.println("Hello");
        System.out.println("Bye") // ✗
    }
}
TEXT
error: ';' expected

Это ошибка компиляции: компилятор отказался переводить текст, и программа не запустилась. Hello тоже не напечатано, хотя первая инструкция верная. Корректор вернул партитуру целиком, и оркестр не сыграл ни такта.

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

Как читать сообщение

Целиком первая строка сообщения выглядит так: Main.java:4: error: ';' expected. Разберём её слева направо:

  1. Main.java — файл с ошибкой.
  2. 4 — номер строки.
  3. error: ';' expected — что нарушено: здесь ожидалась точка с запятой.

Под этой строкой javac повторяет строку программы и ставит знак ^ там, где заметил ошибку. В конце он пишет, сколько ошибок нашёл: 1 error. При запуске через java Main.java добавляется ещё строка error: compilation failed — «компиляция не удалась».

Неизвестное имя

Вторая частая ошибка — имя, которого Java не знает. Здесь в имени метода пропущена буква:

JAVA
System.out.printn("Hi"); // ✗
TEXT
error: cannot find symbol
  symbol:   method printn(String)
  location: variable out of type PrintStream

cannot find symbol значит «имя не найдено». Две строки под ним уточняют, что и где искали:

  • symbol — какое имя не найдено: метод printn, которому передали строку;
  • location — где его искали: в System.out; PrintStream — класс, в котором лежат print и println.

Исправьте имя на println, и программа скомпилируется.

Здесь картинка с корректором неточна. Настоящий корректор заметил бы и опечатку в слове "Helo". Компилятор проверяет правила и имена языка, а текст в кавычках не читает: println("Helo") он пропустит, и опечатку вы увидите только в выводе.

Сначала первая ошибка

Одна ошибка может породить несколько сообщений. Здесь у текста забыли кавычки:

JAVA
System.out.println(Hello Java); // ✗
TEXT
error: ')' or ',' expected
error: not a statement
error: ';' expected

Без кавычек компилятор читает Hello и Java как два имени подряд и запутывается: три сообщения на одну строку. Добавьте кавычки, "Hello Java", и пропадут все три.

Поэтому исправляйте ошибки сверху вниз. Исправив первую, запустите компиляцию снова: следующие сообщения часто исчезают вместе с ней.

Частая ошибка

Имя написали со строчной буквы:

JAVA
system.out.println("Hi"); // ✗
TEXT
error: package system does not exist

Java различает регистр — заглавные и строчные буквы. System и system для неё два разных имени, и второго нет. Сообщение выглядит странно: javac решил, что system — пакет, группа классов, и такого пакета не нашёл. Но виновата всего одна строчная s.

Так же различаются String и string, main и Main. Имена в Java пишут ровно так, как их задали, буква в букву.

Главное

  • Ошибку компиляции находит компилятор до запуска: программа не запускается, и не выполняется ни одна строка, даже верная.
  • Сообщение Main.java:4: error: … называет файл, номер строки и нарушенное правило.
  • cannot find symbol значит, что Java не знает имени; Java различает заглавные и строчные буквы во всех именах.
  • Исправляйте первую ошибку первой: остальные сообщения часто исчезают вместе с ней.