6. Pacotes – Organizando suas classes e bibliotecas

Organização

Quando um programador utiliza as classes feitas por outro, surge um problema clássico: como escrever duas classes com o mesmo nome?

Por exemplo: pode ser que a minha classe de Data funcione de um certo jeito, e a classe Data de um colega, de outro jeito. Pode ser que a classe de Data de uma bibliotecafuncione ainda de uma terceira maneira diferente.

Como permitir que tudo isso realmente funcione? Como controlar quem quer usar qual classe de Data?

Pensando um pouco mais, notamos a existência de um outro problema e da própria solução: o sistema operacional não permite a existência de dois arquivos com o mesmo nome sob o mesmo diretório, portanto precisamos organizar nossas classes em diretórios diferentes.

Os diretórios estão diretamente relacionados aos chamados pacotes e costumam agrupar classes de funcionalidades similares ou relacionadas.

Por exemplo, no pacote java.util temos as classes DateSimpleDateFormat e GregorianCalendar; todas elas trabalham com datas de formas diferentes.

 

Diretórios

Se a classe Cliente está no pacote contas, ela deverá estar no diretório com o mesmo nome: contas. Se ela se localiza no pacote br.com.caelum.contas, significa que está no diretório br/com/caelum/contas.

A classe Cliente, que se localiza nesse último diretório mencionado, deve ser escrita da seguinte forma:

Fica fácil notar que a palavra chave package indica qual o pacote/diretório contém esta classe.

Um pacote pode conter nenhum ou mais subpacotes e/ou classes dentro dele.

Import

Para usar uma classe do mesmo pacote, basta fazer referência a ela como foi feito até agora simplesmente escrevendo o próprio nome da classe. Se quisermos que a classe Bancofique dentro do pacote br.com.caelum.contas, ela deve ser declarada assim:

Para a classe Cliente ficar no mesmo pacote, seguimos a mesma fórmula:

A novidade chega ao tentar utilizar a classe Banco (ou Cliente) em uma outra classe que esteja fora desse pacote, por exemplo, no pacote br.com.caelum.contas.main:

Repare que precisamos referenciar a classe Banco com todo o nome do pacote na sua frente. Esse é o conhecido Fully Qualified Name de uma classe. Em outras palavras, esse é o verdadeiro nome de uma classe, por isso duas classes com o mesmo nome em pacotes diferentes não conflitam.

Mesmo assim, ao tentar compilar a classe anterior, surge um erro reclamando que a classe Banco não está visível.

Acontece que as classes só são visíveis para outras no mesmo pacote e, para permitir que a classe TesteDoBanco veja e acesse a classe Banco em outro pacote, precisamos alterar essa última e transformá-la em pública:

A palavra chave public libera o acesso para classes de outros pacotes. Do mesmo jeito que o compilador reclamou que a classe não estava visível, ele reclama que o atributo/variável membro também não está. É fácil deduzir como resolver o problema: utilizando novamente o modificador public:

Podemos testar nosso exemplo anterior, lembrando que utilizar atributos como público não traz encapsulamento e está aqui como ilustração.

Voltando ao código do TesteDoBanco, é necessário escrever todo o pacote para identificar qual classe queremos usar? O exemplo que usamos ficou bem complicado de ler:

Existe uma maneira mais simples de se referenciar a classe Banco: basta importá-la do pacote br.com.caelum.contas:

Isso faz com que não precisemos nos referenciar utilizando o fully qualified name, podendo utilizar Banco dentro do nosso código em vez de escrever o longo br.com.caelum.contas.Banco.

import x.y.z.*; 

É possível “importar um pacote inteiro” (todas as classes do pacote, exceto os subpacotes) através do coringa *:

Importar todas as classes de um pacote não implica em perda de performance em tempo de execução, mas pode trazer problemas com classes de mesmo nome! Além disso, importar de um em um é considerado boa prática, pois facilita a leitura para outros programadores. Uma IDE como o Eclipse já vai fazer isso por você, assim como a organização em diretórios.

Acesso aos atributos, construtores e métodos

Os modificadores de acesso existentes em Java são quatro, e até o momento já vimos três, mas só explicamos dois.

  • public – Todos podem acessar aquilo que for definido como public. Classes, atributos, construtores e métodos podem ser public.
  • protected – Aquilo que é protected pode ser acessado por todas as classes do mesmo pacote e por todas as classes que o estendam, mesmo que essas não estejam no mesmo pacote. Somente atributos, construtores e métodos podem ser protected.
  • padrão (sem nenhum modificador) – Se nenhum modificador for utilizado, todas as classes do mesmo pacote têm acesso ao atributo, construtor, método ou classe.
  • private – A única classe capaz de acessar os atributos, construtores e métodos privados é a própria classe. Classes, como conhecemos, não podem ser private, mas atributos, construtores e métodos sim.

Usando o Eclipse com pacotes

Você pode usar a perspectiva Java do Eclipse. A view principal de navegação é o Package Explorer, que agrupa classes pelos pacotes em vez de diretórios (você pode usá-la em conjunto com a Navigator, basta também abri-la pelo Window/Show View/Package Explorer).

 

 

Antes de movermos nossas classes, declare-as como públicas e coloque-as em seus respectivos arquivos: um arquivo para cada classe.

Você pode mover uma classe de pacote arrastando-a para o destino desejado. Repare que o Eclipse já declara packages e imports necessários:

 

 

No Eclipse nunca precisamos declarar um import, pois ele sempre vai sugerir isso quando usarmos o Ctrl+Espaço no nome de uma classe.

Você também pode usar o Ctrl+1 no caso da declaração de pacote possuir algum erro.

  • 7. Ferramentas: jar e javadoc