В большинстве ответов здесь говорится, что в Java нет такого понятия, как подпакет, но это не совсем точно. Этот термин был в Спецификации языка Java еще в Java 6, и, вероятно, еще в далеком прошлом (кажется, не существует свободно доступной версии JLS для более ранних версий Java). Язык вокруг подпакетов не сильно изменился в JLS со времени Java 6.
Членами пакета являются его подпакеты и все типы классов верхнего уровня и типы интерфейсов верхнего уровня, объявленные во всех единицах компиляции пакета.
Например, в API платформы Java SE:
- Пакет
java
имеет подпакеты awt
, applet
, io
, lang
, net
, и util
, но нет единицы компиляции.
- Пакет
java.awt
имеет названный подпакет image
, а также несколько модулей компиляции, содержащих объявления классов и типов интерфейса.
Понятие подпакета является актуальным, так как обеспечивает соблюдение ограничений именования между пакетами и классами / интерфейсами:
Пакет может не содержать двух элементов с одинаковыми именами, или в результате ошибки во время компиляции.
Вот некоторые примеры:
- Поскольку пакет
java.awt
имеет подпакет image
, он не может (и не содержит) объявления именованного класса или типа интерфейса image
.
- Если есть пакет с именем
mouse
и типом члена Button
в этом пакете (который затем может называться mouse.Button
), то не может быть пакета с полностью определенным именем mouse.Button
или mouse.Button.Click
.
- Если
com.nighthacks.java.jag
это полное имя типа, то не может быть любой пакет, полное имя либо com.nighthacks.java.jag
или com.nighthacks.java.jag.scrabble
.
Тем не менее, это ограничение именования является единственным значением, придаваемым подпакетам языком:
Предполагается, что иерархическая структура имен для пакетов удобна для организации связанных пакетов обычным способом, но сама по себе не имеет никакого значения, кроме запрета на пакет, имеющий подпакет с тем же простым именем, что и тип верхнего уровня, объявленный в этом пакете. ,
Например, не существует особых отношений доступа между именованным пакетом oliver
и другим названным пакетом oliver.twist
или между именованными пакетами evelyn.wood
и evelyn.waugh
. То есть код в названном пакете oliver.twist
не имеет лучшего доступа к типам, объявленным в пакете, oliver
чем код в любом другом пакете.
В этом контексте мы можем ответить на сам вопрос. Поскольку в явном виде нет специальных отношений доступа между пакетом и его подпакетом или между двумя различными подпакетами родительского пакета, в языке нет способа сделать метод видимым для двух различных пакетов запрошенным способом. Это задокументированное, намеренное проектное решение.
Либо метод можно сделать общедоступным, и все пакеты (включая odp.proj
и odp.proj.test
) смогут получить доступ к указанным методам, либо метод можно сделать частным пакетом (видимость по умолчанию), и весь код, которому требуется прямой доступ к нему, должен быть помещен в тот же (суб) пакет, что и метод.
Тем не менее, очень стандартная практика в Java - помещать тестовый код в тот же пакет, что и исходный код, но в другом месте файловой системы. Например, в инструменте сборки Maven условием было бы поместить эти исходные и тестовые файлы в src/main/java/odp/proj
и
src/test/java/odp/proj
, соответственно. Когда инструмент сборки компилирует это, оба набора файлов оказываются в odp.proj
пакете, но только src
файлы включены в производственный артефакт; тестовые файлы используются только во время сборки для проверки рабочих файлов. С этой настройкой тестовый код может свободно обращаться к любому пакету частного или защищенного кода кода, который он тестирует, так как они будут в одном пакете.
В случае, если вам нужен общий доступ к коду между подпакетами или пакетами одного уровня, который не является тестовым / производственным вариантом, одним из решений, которое я видел в некоторых библиотеках, является размещение этого общего кода как общедоступного, но документа, который предназначен для внутренней библиотеки. использовать только.