Имя пакета отличается от структуры папки, но все равно код Java компилируется - PullRequest
23 голосов
/ 06 декабря 2011

Я использую Notepad ++ для написания своего Java-кода и командную строку для его компиляции и запуска.Ниже приведен пример кода Java,

    package abraKadabra;

    public class SuperClass{
       protected int anInstance;

       public static void main(String [] abc){
           System.out.println("Hello");
       }
    }

Однако этот файл имеет следующую структуру папок:

"usingprotected \ superPkg" (usingProtected - это папка где-то в иерархии в C:)

Итак, имя моего пакета здесь должно быть примерно таким, как использование Protected.superPkg вместо abraKadabra, как я его написал.

Но, когда я компилирую этот код Java из командной строки, он прекрасно компилируется снет ошибок или предупреждений.Почему это так?Разве имя пакета не должно соответствовать структуре папок?И если он должен, как он будет придерживаться?

Например, если мое имя пакета использует Protected.superPkg, будет ли компилятор проверять в обратном порядке.Текущий рабочий каталог должен быть superPkg, тогда родительский каталог должен использовать Protected и все готово.Это как проверить структуру папок с именем пакета?

Ответы [ 4 ]

48 голосов
/ 06 декабря 2011

Спецификация языка Java не заставляет файлы находиться в определенном каталоге. Опционально позволяет компилятору требовать, чтобы публичные классы находились в файлах с одинаковым именем класса, но я не думаю, что есть что-то похожее для пакетов. В разделе 7.2.1 говорится о возможных опциях хранения в файловой системе, но, насколько я вижу, ничего не говорится об обеспечении структуры исходного кода.

Тем не менее, это лучшая практика - и в значительной степени общепризнанное соглашение - отражать структуру пакета в структуре исходного каталога ... и javac будет использовать это, чтобы попытаться найти исходные файлы, которые не ' t явно указано для компиляции.

Обратите внимание, что если вы компилируете из командной строки, по умолчанию каждый класс будет отображаться в том же месте, что и соответствующий исходный файл, но если вы используете опцию "-d" (например, "-d bin"), Компилятор создаст для вас подходящую структуру выходных каталогов, основанную на указанной директории.

6 голосов
/ 07 декабря 2011

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

Предположим, что мой исходный файл Java следующий: -

    package mySample;


    public abstract class Sample{
        public static void main(String... a){
           System.out.println("Hello ambiguity");
        }
    }

Этот файл находится в каталоге "D: \ Code N Code \ CommandLine".

Теперь при компиляции исходного кода (перейдя в вышеуказанный каталог из cmd) с помощью следующей команды: -

    javac -d . Sample.java

Это автоматически создает папку «mySample» в моем текущем каталоге. Итак, мой файл класса Sample.class находится в каталоге «D: \ Code N Code \ CommandLine \ mySample». Компилятор создал эту новую папку «mySample» из имени пакета, которое я дал в своем исходном коде.

Так что, если бы я дал имя моего пакета как «package com.mySample», компилятор создал бы два каталога и поместил мой файл класса в «D: \ Code N Code \ CommandLine \ com \ mySample».

Теперь я все еще нахожусь в текущем рабочем каталоге, то есть в "D: \ Code N Code \ CommandLine". И чтобы запустить мой файл класса, я даю следующую команду:

    java mySample.Sample

Итак, я даю полную иерархию пакетов, а затем имя класса. Интерпретатор Java будет искать в текущем каталоге каталог «mySample», а в каталоге «Sample.class». Он понимает это правильно и запускает это успешно. :)

Теперь, когда я спросил, почему он компилирует мой неверный исходный код пакета, он успешно скомпилирует код, но при запуске файла класса выдает NoClassDefFoundError. Таким образом, вышеуказанный метод может быть использован для использования имен пакетов из командной строки.

4 голосов
/ 06 декабря 2011

Если вы компилируете один класс, javac не нужно искать его в другом месте.Он просто скомпилирует файл как есть и поместит полученный .class в ту же папку.Однако вы, как правило, не сможете использовать класс, пока не поместите его в каталог «abraKadabra» в одном из каталогов в пути к классам.

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

0 голосов
/ 26 августа 2017

Компилятор Java не проверяет структуру каталогов при компиляции исходных файлов.Как вы упомянули, предположим, что у вас есть исходный файл, который начинается с директивы

package abraKadabra;

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

...