Більшість відповідей тут зазначають, що в Java немає такого поняття, як підпакет, але це не є строго точною. Цей термін був включений у специфікацію мови Java аж до Java 6, і, ймовірно, ще більше назад (здається, що для попередніх версій Java не існує вільнодоступної версії JLS). Мова навколо підпакетів мало змінилася в JLS після Java 6.
Членами пакету є його підпакети та всі типи класів верхнього рівня та типи інтерфейсів верхнього рівня, оголошені у всіх блоках компіляції пакету.
Наприклад, в API SE SE Platform:
- Пакет
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
файли включаються у виробничий артефакт; тестові файли використовуються лише під час збирання для перевірки виробничих файлів. За допомогою цієї установки тестовий код може вільно отримувати доступ до будь-якого приватного або захищеного коду пакета коду, який він тестує, оскільки вони будуть знаходитися в одному пакеті.
У випадку, коли ви хочете ділитися кодом у підпакеті чи пакетів братів, що не є тестовим / виробничим випадком, одне рішення, яке я бачив у деяких бібліотеках, - це розмістити цей спільний код як загальнодоступний, але документ, що він призначений для внутрішньої бібліотеки використовувати тільки.