Modificador de acesso "público" Java
1. Visão geral
Neste artigo rápido, cobriremos o modificadorpublic em detalhes e discutiremos quando e como usá-lo com classes e membros.
Além disso, ilustraremos as desvantagens de usar campos de dados públicos.
Para uma visão geral dos modificadores de acesso, definitivamente dê uma olhada em nosso artigo emAccess Modifiers in Java.
2. Quando usar o modificador de acesso público
Classes e interfaces públicas, juntamente com membros públicos, definem uma API. É aquela parte do nosso código que outras pessoas podem ver e usar para controlar o comportamento dos nossos objetos.
No entanto, o uso excessivo do modificador público viola o princípio de encapsulamento da Programação Orientada a Objetos (OOP) e tem algumas desvantagens:
-
Aumenta o tamanho de uma API, dificultando o uso dos clientes
-
Está se tornando mais difícil mudar nosso código porque os clientes confiam nele - qualquer mudança futura pode quebrar seu código
3. Interfaces e classes públicas
3.1. Interfaces Públicas
A public interface defines a specification that can have one or more implementations. Essas implementações podem ser fornecidas por nós ou escritas por outros.
Por exemplo, a API Java expõe a interfaceConnection para definir as operações de conexão do banco de dados, deixando a implementação real para cada fornecedor. No tempo de execução, obtemos a conexão desejada com base na configuração do projeto:
Connection connection = DriverManager.getConnection(url);
O métodogetConnection retorna uma instância de uma implementação específica de tecnologia.
3.2. Classes Públicas
Definimos classes públicas para que os clientes possam usar seus membros por instanciação e referência estática:
assertEquals(0, new BigDecimal(0).intValue()); // instance member
assertEquals(2147483647, Integer.MAX_VALUE); // static member
Além disso, podemos projetar classes públicas para herança usando o modificador opcionalabstract. When we’re using the abstract modifier, the class is like a skeleton that has fields and pre-implemented methods that any concrete implementation can use, além de possuir métodos abstratos que cada subclasse precisa implementar.
Por exemplo, a estrutura de coleções Java fornece a classeAbstractList como base para a criação de listas personalizadas:
public class ListOfThree extends AbstractList {
@Override
public E get(int index) {
//custom implementation
}
@Override
public int size() {
//custom implementation
}
}
Portanto, só temos que implementar os métodosget()esize(). Outros métodos comoindexOf()econtainsAll() já estão implementados para nós.
3.3. Classes públicas aninhadas e interfaces
Semelhante às classes e interfaces públicas de nível superior, classes e interfaces públicas aninhadas definem um tipo de dados API. No entanto, eles são particularmente úteis de duas maneiras:
-
Eles indicam ao usuário final da API que o tipo de nível superior anexo e seus tipos fechados têm um relacionamento lógico e são usados juntos
-
Eles tornam nossa base de código mais compacta, reduzindo o número de arquivos de código-fonte que usaríamos se os tivéssemos declarado como classes e interfaces de nível superior
Um exemplo é a interfaceMap.Entry da API Java principal:
for (Map.Entry entry : mapObject.entrySet()) { }
Criar a interface aninhadaMap.Entry a relaciona-a fortemente com a interfacejava.util.Map e nos salvou de criar outro arquivo dentro do pacotejava.util.
Por favor, leia o artigonested classes para mais detalhes.
4. Métodos públicos
Os métodos públicos permitem que os usuários executem operações prontas. Um exemplo é o método públicotoLowerCase na APIString:
assertEquals("alex", "ALEX".toLowerCase());
Podemos tornar um método público estático com segurança se ele não usar nenhum campo de instância. O métodoparseInt da classeInteger é um exemplo de método estático público:
assertEquals(1, Integer.parseInt("1"));
Os construtores são geralmente públicos para que possamos instanciar e inicializar objetos, embora às vezes possam ser privados, como emsingletons.
5. Campos públicos
Os campos públicos permitem alterar diretamente o estado de um objeto. The rule of thumb is that we shouldn’t use public fields. Existem várias razões para isso, como estamos prestes a ver.
5.1. Segurança de Thread
Usar visibilidade pública com campos não finais ou campos mutáveis finais não é seguro para threads. Não podemos controlar a alteração de suas referências ou estados em diferentes threads.
Verifique nosso artigo emthread-safety para saber mais sobre como escrever código thread-safe.
5.2. Executando ações em modificações
Não temos controle sobre um campo público não final porque sua referência ou estado pode ser definido diretamente.
Em vez disso, é melhor ocultar os campos usando um modificador privado e usar um setter público:
public class Student {
private int age;
public void setAge(int age) {
if (age < 0 || age > 150) {
throw new IllegalArgumentException();
}
this.age = age;
}
}
5.3. Alterando o tipo de dados
Os campos públicos, mutáveis ou imutáveis, fazem parte do contrato do cliente. É mais difícil alterar a representação de dados desses campos em uma versão futura porque os clientes podem precisar refatorar suas implementações.
Ao dar aos campos escopo privado e usar acessadores, temos a flexibilidade de alterar a representação interna, mantendo também o tipo de dados antigo:
public class Student {
private StudentGrade grade; //new data representation
public void setGrade(int grade) {
this.grade = new StudentGrade(grade);
}
public int getGrade() {
return this.grade.getGrade().intValue();
}
}
A única exceção para o uso de campos públicos é o uso de campos imutáveis finais estáticos para representar constantes:
public static final String SLASH = "/";
6. Conclusão
Neste tutorial, vimos que o modificador público é usado para definir uma API.
Além disso, descrevemos como o uso excessivo desse modificador pode restringir a capacidade de introduzir melhorias em nossa implementação.
Finalmente, discutimos por que é uma má prática usar modificadores públicos para campos.
E, como sempre, os exemplos de código deste artigo estão disponíveisover on GitHub.