A maioria das respostas aqui afirmou que não existe um subpacote em Java, mas isso não é estritamente preciso. Esse termo está presente na Especificação da Linguagem Java já em Java 6 e provavelmente mais atrás (não parece haver uma versão acessível do JLS para versões anteriores do Java). O idioma em torno dos subpacotes não mudou muito no JLS desde o Java 6.
Os membros de um pacote são seus subpacotes e todos os tipos de classe de nível superior e tipos de interface de nível superior declarados em todas as unidades de compilação do pacote.
Por exemplo, na API da plataforma Java SE:
- O pacote
java
tem subpackages awt
, applet
, io
, lang
, net
, e util
unidades, mas não compilação.
- O pacote
java.awt
possui um subpacote nomeado image
, além de várias unidades de compilação que contêm declarações de classe e tipos de interface.
O conceito de subpacote é relevante, pois reforça as restrições de nomenclatura entre pacotes e classes / interfaces:
Um pacote não pode conter dois membros com o mesmo nome ou resultados de erro em tempo de compilação.
aqui estão alguns exemplos:
- Como o pacote
java.awt
possui um subpacote image
, ele não pode (e não contém) uma declaração de uma classe ou tipo de interface nomeado image
.
- Se houver um pacote nomeado
mouse
e um tipo de membro Button
nesse pacote (que pode ser chamado de mouse.Button
), não poderá haver nenhum pacote com o nome completo mouse.Button
ou mouse.Button.Click
.
- Se
com.nighthacks.java.jag
é o nome completo de um tipo, não pode haver nenhum pacote cujo nome completo seja com.nighthacks.java.jag
ou com.nighthacks.java.jag.scrabble
.
No entanto, essa restrição de nomenclatura é o único significado concedido aos subpacotes pelo idioma:
A estrutura hierárquica de nomenclatura para pacotes deve ser conveniente para organizar pacotes relacionados de maneira convencional, mas não tem significado em si mesma além da proibição de um pacote com um subpacote com o mesmo nome simples que um tipo de nível superior declarado nesse pacote .
Por exemplo, não há relacionamento de acesso especial entre um pacote nomeado oliver
e outro pacote nomeado oliver.twist
, ou entre pacotes nomeados evelyn.wood
e evelyn.waugh
. Ou seja, o código em um pacote nomeado oliver.twist
não tem melhor acesso aos tipos declarados no pacote do oliver
que o código em qualquer outro pacote.
Nesse contexto, podemos responder à pergunta em si. Como não há explicitamente nenhum relacionamento de acesso especial entre um pacote e seu subpacote, ou entre dois subpacotes diferentes de um pacote pai, não há como, no idioma, tornar um método visível para dois pacotes diferentes da maneira solicitada. Esta é uma decisão de projeto intencional documentada.
O método pode ser tornado público e todos os pacotes (incluindo odp.proj
e odp.proj.test
) poderão acessar os métodos fornecidos, ou o método pode tornar o pacote privado (a visibilidade padrão) e todo o código que precisa acessá-lo diretamente deve incluir o mesmo (sub) pacote que o método
Dito isto, uma prática muito padrão em Java é colocar o código de teste no mesmo pacote que o código-fonte, mas em um local diferente no sistema de arquivos. Por exemplo, na ferramenta de criação do Maven , a convenção seria colocar esses arquivos de origem e teste em src/main/java/odp/proj
e
src/test/java/odp/proj
, respectivamente. Quando a ferramenta de construção compila isso, os dois conjuntos de arquivos acabam no odp.proj
pacote, mas apenas os src
arquivos são incluídos no artefato de produção; os arquivos de teste são usados apenas no momento da construção para verificar os arquivos de produção. Com essa configuração, o código de teste pode acessar livremente qualquer pacote de código privado ou protegido do código que está testando, pois eles estarão no mesmo pacote.
No caso em que você deseja compartilhar o código entre subpacotes ou pacotes irmãos que não é o caso de teste / produção, uma solução que já vi algumas bibliotecas usar é colocar esse código compartilhado como público, mas documentar que ele se destina à biblioteca interna usarem apenas.