Как скомпилировать java-файл из консоли
24-06-2018Время чтения ~ 7 мин.Java 11658
Компиляция java-программы без проблем работает ровно до того момента, пока не потребуется создать что-то сложнее одного файла в проекте. Когда я попытался использовать два java-файла в разных каталогах, компилятор напрочь отказался работать, выдавая загадочные сообщения вроде «cannot find symbol»: чисто интуитивно я понял, что он просто не видит второй исходный файл.
Что может означать команда import
(импорт)? Опять же интуитивно — это какой-то импорт из другого файла, например его подключение. В Java это означает лишь «расширение» области видимости — эдакое namespace, которое призвано исключить конфликт одинаковых имён. Никакого импорта здесь и в помине нет.
Другой пример — что такое package
(пакет)? Какой-то пакет — набор модулей, файлов под одним именем, может архив. Ан, нет! В Jave к пакетам это никакого отношения не имеет — это всего лишь каталог. Причём каталог, который указывается в полном имени. Или чтобы его не указывать (частично), нужно задать его в import
. О как!
При чём тут компиляция? А при том, что компилятор не шибко умный: чтобы он нормально заработал потребуется указать дополнительные параметры, которые завязаны на каталоги, файлы и классы (читай: «package» и «import»).
Проблемы?
Какие могут возникнуть проблемы? Вот список того, с чем мне пришлось столкнуться.
- В консоли русские тексты крокозяблами.
- Если исходные файлы в отдельных каталогах, компилятор их не видит.
- Компилятор требует строгого соответствия указанным package в исходном коде реальной структуре подкаталогов.
- Чтобы отделить скомпилированные class-файлы от java-файлов, также требуется указывать дополнительные параметры.
- Каждый Java-проект имеет свои настройки, поскольку у них разные имена main-классов (его следует указывать при запуске программы на выполнение).
Тут ещё есть такой нюанс, что структура ява-программ у всех разная. В одних проектах для исходных файлов используется каталог src, в других java. Для скомпилированных часто встречаются варианты: bin и classes.
Что касается package, то тут всё значительно сложней, поскольку настоятельно рекомендуется создавать свои уникальные (в пределах всего Интернета) пространство имён. Например для моих программ (если их выкладывать в Сети) потребуется сделать такую структуру каталогов для Hello: org/maxsite/java/Hello.java
.
В полноценных IDE, вроде Eclipse, данный вопрос решается просто — программа сама подставляет нужные параметры и компиляция работает из «коробки». Правда при этом создаётся куча служебных файлов. Но что делать, если нужно выполнить компиляцию из консоли? Скажем в том же Notepad++. Я потратил на решение несколько дней, поделюсь с вами.
Правила для Java-программ
Первое правило — каждая ява-программа должна находиться в своём каталоге. Какой бы она не была примитивной. Только так можно обеспечить корректную работу компилятора, который сам просто не понимает, где корень проекта.
Второе правило — исходые файлы нужно отделять от скомпилированных, иначе образуется страшное мессиво.
Третье правило — всегда используется хоть какой-то package, который указывает на «базовый» или «основной» подкаталог в каталоге исходных файлах.
Четвёртое правило — все исходные программы пишутся в UTF8 без сигнатуры BOM.
Структура файлов/каталогов
Чтобы было понятно, покажу на примере демо-программы HelloAlpha. Это очень простая программа, которая выводит сообщения из кучи одноименных классов. Я её написал, пытаясь разобраться с тонкостями import и package и возможно вам она окажется тоже полезной.
Программа имеет свой каталог проекта, который у меня расположен как d:\android\java\HelloAlpha\ У вас он может находиться в другом месте.
Каталог src — это исходные java-файлы с подкаталогами, которые совпадают со структурой package.
Напомню, что в тексте программы каталоги package указываются через точку вместо слэша. Вместоpackage mypackage/first;
указываетсяpackage mypackage.first;
Каталог bin используется для размещения скомпилированных class-файлов. Компилятор сам повторит структуру подкаталогов из src. В Notepad++ исходный проект выглядит так:
Файл compiling_and_run.bat используется для компиляции, а start.bat для запуска уже скомпилированного проекта (ему src не нужен).
Файл Alpha.java размещён в разных подкаталогах и представляет собой код, который просто выводит сообщение в консоль. Вот пример mypackage/first/Alpha.java:
package mypackage.first; public class Alpha{ public void out(String s){ System.out.println(" mypackage/first/Alpha.java" + " " + s); } }
Вы можете загрузить zip-архив со всеми файлами: HelloAlpha.zip
В каждом подкаталоге Alpha.java немного разный: указан свой package и своё сообщение. Оно и используется для исследования (это тема другой статьи). :-)
После запуска compiling_and_run.bat произойдет компиляция и запуск программы на выполнение.
Компиляция
Теперь подходим к самому интересному — компиляции. Перед тем, как её запускать, в файле compiling_and_run.bat укажите полный каталог проекта.
set DIR_PROJECT=d:\android\java\HelloAlpha\
Если этого не сделать, то запускать bat-файл можно будет только из каталога проекта, но не получится из того же Notepad++. Второй момент — перед компиляцией удаляются все class-файлы из bin-каталога. Это сделано умышлено, поскольку в процессе программирования может быть сделано множество постороних class-файлов, которые компилятор сам не удаляет. Если же эта возможность не требуется, то удалите или закомментируйте строчку
del /s %DIR_BIN%\*.class >NUL
Сейчас bat-файл настроен на HelloAlpha, поэтому после запуска (после указания своего каталога!) вы увидите что-то вроде такого:
Если возникнет ошибка компиляции, то будет немного другой экран:
При этом, запуска на выполнение уже не будет.
Настройка bat-файла
Все настройки я вынес в верх файла compiling_and_run.bat:
set DIR_PROJECT=d:\android\java\HelloAlpha\ set MAIN_PACKAGE_DIR=mypackage set MAIN_PACKAGE=mypackage set MAIN_CLASS=HelloAlpha set DIR_SRC=src set DIR_BIN=bin
- DIR_PROJECT — каталог проекта. Нужно указать слэш в конце.
- MAIN_PACKAGE_DIR — «основной» пакет, то есть тот каталог, где размещается файл «запуска». Указывается относительно каталога src.
- MAIN_PACKAGE — тот же «основной» пакет, но только разделители каталогов «\» указываются точками «.». Такое разделение — требование java.
- MAIN_CLASS — это собственно то, что является программой. Для запуска java-программ указывается файл без расширения .class.
- DIR_SRC — каталог исходных файлов. Именно он является «точкой отсчёта» для всех java-файлов.
- DIR_BIN — в этот каталог складываем готовые файлы. Он может использоваться и для генерации jar-файла.
Разделение на MAIN_PACKAGE_DIR и MAIN_PACKAGE требуется, если у вас «длинный» пакет. Например для org.maxsite.java
set MAIN_PACKAGE_DIR=org\maxsite\java set MAIN_PACKAGE=org.maxsite.java
Файл compiling_and_run.bat я сделал так, чтобы он работал в «правильной» кодировке, а также отслеживал ошибки компиляции. А цветовая дифференциация штанов раскраска немного упрощает отладку.
Учитывайте, что для java регистр файлов и каталогов имеет значение!
Файл start.bat используется для тех случаев, если нужно просто запустить программу без компиляции. Поскольку там одна строчка для Java, то просто укажите свой package и main-класс.
Порядок создания java-проекта
Схема простая: создать каталог проекта, скопировать структуру каталогов и bat-файлы. Поправить в них package и main-класс. Файл compiling_and_run.bat можно вообще переименовать под имя проекта (например HelloAlpha.bat).
Работа в Notepad++ с Java
Уж коли я затронул Notepad++, то покажу как настроить в нём компиляцию. В программе есть меню Запуск:
Здесь нужно выбрать compiling_and_run.bat.
Можно нажать Сохранить... и указать название команды и горячую клавишу, например F9
.
Если будет конфликт, то выскочит подсказка. После этого появится пункт меню, по которой и происходит запуск bat-файла.
Существует ещё один способ: использование плагина NppExec. Но с ним довольно сложно, поскольку каждый проект потребует отдельной настройки, которую всё-таки проще сделать один раз в bat-файле.
Файл HelloAlpha.java
Изучение самого проекта HelloAlpha.java немного выходит за рамки этой статьи. Я её написал только для изучения команд package и import. Научной ценности она, естественно, не имеет. :-) Поэтому для каркаса своих java-программ вы можете придумать свою структуру. Главное, пожалуй оставить каталог mypackage (или свой вариант), поскольку хоть какой-то должен указываться в package исходных файлов.