Сначала скомпилировать, потом запустить
Теперь, когда у вас установлен JDK, запуск Java - это двухэтапный цикл. В отличие от скриптового языка, где вы направляете интерпретатор на файл и сразу запускаете, Java сначала компилирует ваш читаемый человеком исходный код в байт-код, а затем отдельный шаг запускает этот байт-код на JVM.
Эти два шага соответствуют двум инструментам командной строки, которые поставляются с JDK:
javac- компилятор. Он читаетMain.javaи записываетMain.class(байт-код).java- загрузчик. Он запускает JVM и выполняет байт-код изMain.class.
Вы можете запустить любой самодостаточный пример прямо здесь, на странице - редактор ниже выполнит оба шага за вас. Но стоит понять, что происходит на вашей собственной машине, потому что именно там живут настоящие проекты.
Две команды на вашей машине
Допустим, у вас есть этот код, сохранённый как Main.java:
public class Main {
public static void main(String[] args) {
System.out.println("Hello from the terminal");
}
}
Откройте терминал в папке, содержащей файл, и запустите компилятор:
javac Main.java
Если код компилируется без ошибок, javac ничего не выводит и создаёт новый файл Main.class рядом с вашим исходником. Этот файл .class - это байт-код: он не является читаемым текстом и не привязан к вашей операционной системе.
Теперь запустите его командой java:
java Main
Hello from the terminal
Самая частая ошибка новичков именно здесь: чтобы запустить программу, вы выполняете java, а не javac, и передаёте имя класса без расширения. Это java Main - никогда java Main.class и никогда java Main.java.
Имя файла должно совпадать с публичным классом
Java навязывает правило, которое удивляет новичков: класс public должен находиться в файле с точно таким же именем плюс .java. Класс public class Main должен быть в Main.java. Ошибётесь с регистром - и javac откажется компилировать.
// This is in a file called Greeting.java
public class Greeting { // ERROR: class Greeting should be in Greeting.java... wait, it is
public static void main(String[] args) {
System.out.println("Hi");
}
}
Несоответствие, которое реально мешает людям, более тонкое - назвать файл greeting.java (со строчной буквы), когда класс называется Greeting, или сохранить Main.java, но написать public class Hello. Компилятор сообщает что-то вроде:
Main.java:1: error: class Hello is public, should be declared in a file named Hello.java
Исправление всегда одно и то же: сделайте имя файла и имя публичного класса идентичными, символ в символ.
Сокращённый путь: запустить один файл напрямую
Начиная с JDK 11, вы можете пропустить явный шаг компиляции для одного исходного файла. Команда java скомпилирует его в памяти и запустит за один раз - никакой файл .class на диск не записывается:
java Main.java
Это идеально для быстрых экспериментов и небольших скриптов. Обратите внимание на разницу в том, что вы передаёте:
java Main- запускает уже скомпилированныйMain.class.java Main.java- компилирует и запускает исходный файл за один раз.
Режим одного файла работает только тогда, когда вся ваша программа умещается в один файл. Как только вы разбиваете код на несколько классов в нескольких файлах, вы возвращаетесь к компиляции с помощью javac сначала. Для изучения основ режим одного файла делает цикл коротким.
Передача аргументов вашей программе
Помните String[] args в main? Это аргументы командной строки. Всё, что вы напечатаете после имени класса в команде java, попадает в этот массив:
На своей машине вы передали бы ему аргументы так:
java Main hello world
First argument: hello
Total arguments: 2
Редактор выше не может принимать аргументы из терминала, поэтому он выполняет ветку «нет аргументов» - но тот же код обрабатывает оба случая. Именно так Java-программы читают данные, переданные при запуске, задолго до того, как вы доберётесь до файлов или пользовательского ввода.
Чтение сообщений об ошибках компилятора
Когда javac отвергает ваш код, он сообщает вам файл, строку и что пошло не так. Научиться читать эти сообщения - половина дела в выходе из тупика. Вот классика - пропущенная точка с запятой:
public class Main {
public static void main(String[] args) {
System.out.println("Oops") // no semicolon
}
}
Main.java:3: error: ';' expected
System.out.println("Oops")
^
1 error
Знак вставки (^) указывает на место, где компилятор ожидал что-то. Main.java:3 - это файл и номер строки. Не поддавайтесь желанию угадать - прочитайте строку, исправьте ту единственную вещь, которую он называет, и перекомпилируйте. Ошибки компиляции означают, что ещё ничего не запустилось; ошибки времени выполнения (которые выглядят иначе) означают, что ваша программа запустилась, а затем упала.
Программа для проверки работоспособности
Запустите это в редакторе или сохраните как Main.java и выполните javac Main.java, а затем java Main на своей машине. Если вы видите все три строки, ваш набор инструментов работает от начала до конца:
Здесь появляются три вещи, с которыми вы как следует познакомитесь скоро: переменная int, конкатенация строк с помощью + и массив с его .length. Пока достаточно того, что программа компилируется и выводит результат.
Далее: синтаксис Java
Вы запустили несколько программ, но мы обходили стороной пунктуацию - фигурные скобки, точки с запятой, public static void main и причину, почему каждая строка выглядит именно так. Следующая страница разбирает синтаксис Java по частям, чтобы структура перестала казаться шаблонным кодом и начала обретать смысл.
Часто задаваемые вопросы
Как запустить программу на Java?
Сохраните код в файл, названный так же, как публичный класс (например, Main.java), откройте терминал в этой папке и выполните две команды: javac Main.java, чтобы скомпилировать его в байт-код, а затем java Main, чтобы запустить. С JDK 11 или новее для одного файла можно пропустить первый шаг и просто выполнить java Main.java напрямую.
В чём разница между javac и java?
javac - это компилятор: он читает ваш исходник .java и создаёт файл .class, заполненный байт-кодом. java - это загрузчик: он запускает JVM и выполняет байт-код из файла .class. Вы компилируете один раз с помощью javac, а затем запускаете сколько угодно раз с помощью java.
Почему я получаю ошибку "could not find or load main class"?
Почти всегда потому, что вы передали java неправильное имя. Используйте имя класса, а не имя файла: это java Main, а не java Main.class и не java Main.java. Также убедитесь, что вы находитесь в папке, содержащей Main.class, и что имя класса точно совпадает с именем файла, включая регистр букв.