Continuando nossa série, neste artigo abordaremos os identificadores válidos e as convenções. Analisaremos o relacionamento entre classes e como uma classe pode ter acesso a um membro de outra classe. A nível de organização dividimos este artigo da série em duas partes.

Identificadores e Convenções

Identificadores são nomes dados a variáveis, métodos e classes. Existem regras para criação dos identificadores.

Identificadores

Os identificadores devem iniciar com uma letra, um underscore(_) ou um cifrão($). Não é permitido que os identificadores comecem com um número. Não se pode utilizar uma palavra-chave como identificador. A tabela 1 lista as palavras-chave Java, inclusive “enum”, uma novidade do Java 5.

Tabela 1 - Palavras-chave Java
abstract continue for new switch
assert default goto package synchronized
boolean do if private this
break double implements protected throw
byte else import public throws
case enum instanceof return transient
catch extends int short try
char final interface static void
class finally long strictfp volatile
const float native super while

Padrão JavaBeans

A especificação JavaBeans foi desenvolvida para ser um padrão de desenvolvimento de componentes que, facilmente, possam ser utilizados por desenvolvedores em diferentes IDEs.

É primordial levarmos em conta que programar usando um conjunto de padrões auxilia a diminuir o esforço envolvido em fazer a manutenção, testar e aprimorar qualquer código.

Por esse motivo, a Sun fez um conjunto de padrões de programação em Java, e publicou esses padrões num documento denominado “Convenções de Código Java”.

  • Métodos: a primeira letra em minúsculo. Nas palavras compostas, a primeira letra sempre em caixa baixa, as demais palavras seguintes iniciam por caixa alta.
  • Variáveis: devem seguir a mesma lógica que os métodos. Começam com letra minúscula. Em palavras compostas, a primeira letra sempre em maiúscula, o restante das palavras seguintes iniciam por letra com caixa alta.
  • Classes e interfaces: a letra inicial deve ser maiúscula. Em situações onde os nomes sejam palavras compostas, a primeira letra de cada palavra deve ser maiúscula. Nas classes o nome deve ser sempre substantivo. Nas interfaces o nome deve ser um adjetivo.
  • Constantes: As constantes em Java são criadas marcando as variáveis com os modificadores final e static, ou através de enums. Elas devem ter seus nomes utilizando letras maiúsculas com caracteres underscore (_) como separadores.

Regras de Declaração para Arquivos-Fonte

Vamos primeiro mostrar um arquivo-fonte completo. Na continuação, trataremos dos vários componentes e da ordem em que eles devem estar no arquivo.


        package biblioteca;
        import java.util.regex.*;
        import java.awt.*;
        public class Arquivo{
        String name;
        public String getName() {
        return name;
        }
        public void setName(String name) {
        this.name = name;
        }
        }
        class ClasseA{}
        class ClasseB{}
        
  1. Só é possível existir uma declaração package por arquivo-fonte. Caso a classe faça parte de um pacote, a declaração package deve aparecer na primeira linha do arquivo-fonte, antes de quaisquer declarações import que possam existir.
  2. Se tiver declarações import, elas devem estar entre a declaração package, caso exista, e a declaração da classe. Caso não haja uma declaração package, então as declarações import devem aparecer nas primeiras linhas do arquivo-fonte.
  3. Só é possível a existência de uma classe public por cada arquivo-fonte. Entretanto, podem existir várias classes, com modificadores diferentes de public. Note, novamente, o exemplo acima.
  4. Os comentários podem estar em qualquer linha do arquivo-fonte; eles são independentes de quaisquer regras de posicionamento.
  5. Vamos supor que um arquivo-fonte tenha apenas classes não-public. Nesta hipótese, ele pode ter um nome diferente de quaisquer dessas classes. Partindo-se da premissa de que o arquivo-fonte possua somente a declaração: class ClasseJava { }, ele pode ser compilado com um nome qualquer, finalizado com a extensão .java.
  6. Se existir uma classe public num arquivo, o nome do arquivo, obrigatoriamente, deve ser o mesmo da classe public.

Controle de acesso a classes

Quando se fala que uma classe A tem acesso a uma classe B, isso quer dizer que a classe A pode fazer 3 coisas: criar uma instância da classe B e/ou estender a classe B e/ou acessar determinados métodos, dependendo do controle de acesso desses métodos e atributos.

Se a classe A não poder ver a classe B, o nível de acesso dos métodos e atributos na classe B não fará diferença; a classe A não terá acesso a esses atributos e métodos. Acesso quer dizer visibilidade.

Acesso Padrão

Perceba no exemplo a seguir, em que A e B pertencem ao mesmo pacote. Neste exemplo, o pacote é o pacote-default, uma vez que não existe instrução package no arquivo-fonte.


        class A{
        int x;
        }
        class B extends A{ //Estender a classe
        A objeto = new A(); //Instanciar um objeto
        int y = x; //Acessar um atributo
        }
        

Observe com muita atenção: Ao encontrar uma questão que possua uma lógica complexa, preste atenção nos modificadores de acesso primeiramente. Dessa maneira, ao descobrir uma tentativa de violação de acesso, por exemplo, classe do pacote X tentando acessar uma classe default do pacote Y, você deverá saber que o código não irá compilar, então não precisará entender a lógica do programa.

Modificador/Acesso (public)

Existem apenas 3 modificadores de acesso para 4 níveis de acesso. Os modificadores de acesso são: public, private e protected, os níveis de acesso possuem os 3 modificadores, acrescentando-se o nível de acesso de pacote(default).

Modificadores não-referentes a acesso

Pode-se alterar uma declaração de classe utilizando as palavras-chave final, abstract ou strictfp. Esses modificadores existem em adição a qualquer controle de acesso que há na classe, então é possível declarar uma classe como public e final ao mesmo tempo. Porém, não é em todas as situações que os modificadores não-referentes a acesso podem ser combinados.

Modificador final para classes

Quando utilizada na declaração de classe, a palavra-chave final quer dizer que a classe em questão não pode ser estendida. Ou seja, ela não pode conter subtipos (filhos); não permite a herança.

Várias classes da API são final. Como exemplo temos a classe String que não pode ser estendida. Tente supor a confusão que aconteceria se não existisse garantia no modo como um objeto String funcionaria em qualquer sistema que usasse sua aplicação.

No dia-a-dia, quase nunca iremos criar classes final. As classes final barram um dos benefícios fundamentais da orientação a objetos: a extensibilidade. Dessa maneira, a não ser que se tenha uma grande preocupação com a segurança, admita que algum outro programador poderá estender sua classe.

Classe abstract

A classe abstract tem comportamento completamente oposto ao da classe final. Uma classe abstract não pode ser instanciada diretamente em nenhuma hipótese. A palavra-chave abstract está implicitamente relacionada aos conceitos de herança e de reaproveitamento de código.

Perceba, entretanto, que uma classe abstract pode ser compilada e executada, logicamente, se nenhuma instância dela for criada (diretamente).

Métodos abstratos possuem ponto-e-vírgula(;) na sua terminação em vez de chaves.

Se o método abstract estiver em uma classe e não em uma interface, tanto o método como a classe devem estar marcados com o modificador abstract.

O uso de classes abstract e interfaces permite que se tire vantagens do polimorfismo proporcionando um alto grau de flexibilidade e extensibilidade. Em outras palavras, não existe a possibilidade de marcar uma classe como abstract e final simultaneamente.

Interfaces

Na criação de uma interface, será definido um contrato com o que a classe deve fazer, sem nenhuma menção sobre como a classe que implementa a interface fará.

Qualquer classe pode implementar uma interface, de qualquer árvore de herança. Isso permitirá o uso de classes extremamente diferentes e o fornecimento a elas de uma característica em comum.

Devemos ver uma interface como uma classe 100% abstract. Assim como a classe abstract, a interface define métodos abstract de acordo com o exemplo abaixo:


        package devmedia;

        interface Negociavel{
        void negociar();
        void planejar();
        void discutir();
        }
        interface Compravel{
        void comprar();
        }
        

Entretanto, enquanto uma classe abstract pode definir métodos abstract e não-abstract(concretos), uma interface possui apenas métodos abstract.

Os métodos de interface são implicitamente public e abstract.

Já as variáveis declaradas em uma interface devem ser public, final e static - ou seja, as interfaces só podem declarar constantes. Veja o exemplo abaixo e suas possíveis variações.


        interface Negociavel{
        String a = “Texto”;
        public int b = 30;
        public static double c = 40.05;
        static public String x = “Exemplo”;
        final boolean y = true;
        static public final char z = ‘Z’;
        }
        

Podemos perceber também que os métodos de interface não podem ser static. Já que os métodos da interface são abstract, não podem ser declarados como final, native, synchronized ou strictfp. É possível uma interface estender uma ou várias interfaces.

A partir de agora é absolutamente indispensável que se aceite essa sintaxe. Uma interface “extends” outra interface.


        package devmedia;
        interface Flutuavel{}
        interface Carregavel{}
        interface Unificavel extends Flutuavel, Carregavel{}
        

Não é possivel modificar o valor de uma constante. Uma vez que o valor for atribuído, nunca poderá ser mudado. A atribuição ocorrerá na própria interface onde a constante estiver declarada, então a classe que implementar a interface pode acessar e usar a constante, mas somente como leitura.

A declaração da interface pode possuir o modificador public ou não. Sendo assim, seus níveis de acesso podem ser default ou public. Caso seja default, só pode ser estendida por interfaces do mesmo pacote, ou implementada por classes do mesmo pacote. Enfatizando mais uma vez: um método de interface é sempre abstract e public e uma constante de interface é sempre public static final.


Leia todos artigos da série