1. O que são getters e setters
Se imaginarmos um objeto como um cofre, seus campos privados — são o conteúdo do cofre, e os getters e setters — as chaves para compartimentos individuais. Getters permitem saber o que está lá dentro, e setters permitem colocar algo novo com cuidado (mas só se você não colocar, por exemplo, um ouriço no lugar dos documentos).
Getter
Getter — é um método público (public) que retorna o valor de um campo privado (private). Normalmente seu nome começa com get + nome do campo com letra maiúscula.
public class Person {
private String name; // Campo privado
// Getter para o campo name
public String getName() {
return name;
}
}
Setter
Setter — é um método público (public) que permite alterar o valor de um campo privado. Seu nome começa com set + nome do campo com letra maiúscula.
public class Person {
private String name;
// Setter para o campo name
public void setName(String name) {
this.name = name;
}
}
Para campos boolean
Para campos do tipo boolean costuma-se usar o prefixo is nos getters:
private boolean active;
public boolean isActive() {
return active;
}
public void setActive(boolean active) {
this.active = active;
}
2. Sintaxe e convenções de nomenclatura
Java é uma linguagem rigorosa, mas não chata. Há convenções consolidadas que tornam seu código compreensível para outros desenvolvedores (e para você mesmo daqui a um mês).
- Getter: public Type getNomeDoCampo()
- Setter: public void setNomeDoCampo(Type value)
- Getter para boolean: public boolean isNomeDoCampo()
Nome do campo no método é escrito com inicial maiúscula: se o campo é age, então os métodos serão getAge() e setAge().
Essa convenção segue o estilo JavaBeans, graças ao qual IDEs, bibliotecas e frameworks podem localizar automaticamente seus getters e setters. Por exemplo, se você usa Spring ou JavaFX, esses métodos serão “magicamente” chamados quando necessário.
3. Exemplos de código
Vamos pegar um projeto didático — um aplicativo simples de “contatos” (um análogo de agenda telefônica) — e adicionar getters e setters corretos.
Exemplo: classe Contact com campos privados e getters/setters
public class Contact {
private String name;
private String phone;
private int age;
private boolean favorite;
// Getters
public String getName() {
return name;
}
public String getPhone() {
return phone;
}
public int getAge() {
return age;
}
public boolean isFavorite() {
return favorite;
}
// Setters
public void setName(String name) {
this.name = name;
}
public void setPhone(String phone) {
this.phone = phone;
}
public void setAge(int age) {
// Exemplo de validação: a idade não deve ser negativa
if (age < 0) {
System.out.println("A idade não pode ser negativa!");
return;
}
this.age = age;
}
public void setFavorite(boolean favorite) {
this.favorite = favorite;
}
}
Uso no aplicativo
Contact friend = new Contact();
friend.setName("Ivan Ivanov");
friend.setPhone("+1-999-123-45-67");
friend.setAge(25);
friend.setFavorite(true);
System.out.println("Nome: " + friend.getName());
System.out.println("Telefone: " + friend.getPhone());
System.out.println("Idade: " + friend.getAge());
System.out.println("Favorito: " + (friend.isFavorite() ? "Sim" : "Não"));
Exemplo de validação no setter
Observe que no setter setAge adicionamos uma verificação simples: se a idade for negativa, não alteramos o campo e exibimos um aviso. Esse é um jeito simples de proteger o objeto contra dados incorretos.
4. Boas práticas: como fazer do jeito certo
Nem todos os campos devem ter setters públicos
Às vezes um campo deve ser somente leitura — por exemplo, um identificador único definido na criação do objeto e que não muda mais. Nesse caso, simplesmente não escreva o setter:
public class Contact {
private final int id; // final — não pode ser alterado após a inicialização
public Contact(int id) {
this.id = id;
}
public int getId() {
return id;
}
// Sem setId!
}
Use getters/setters para controle de acesso e validação
public void setName(String name) {
if (name == null || name.trim().isEmpty()) {
System.out.println("O nome não pode ser vazio!");
return;
}
this.name = name;
}
Não exponha diretamente objetos internos mutáveis
Se você tem um campo — por exemplo, uma lista de telefones:
private String[] phones;
Não o retorne diretamente pelo getter:
public String[] getPhones() {
return phones; // Ruim!
}
Esse código permite que código externo altere a lista como quiser — violando a encapsulação!
Melhor: retornar uma cópia do array:
public String[] getPhones() {
return Arrays.copyOf(phones, phones.length); // Retornamos uma cópia
}
Ou simplesmente clonar:
public String[] getPhones() {
return phones.clone();
}
Faça getters e setters claros e simples
- Não escreva lógica de negócios complexa em getters/setters — a tarefa deles é simples: controle de acesso e, se necessário, validação.
- Se o campo não deve mudar — não crie o setter.
- Se o campo não deve estar acessível por fora — não crie o getter.
5. Geração automática de getters/setters na IDE
Escrever acessores manualmente não é lá muito divertido, especialmente se a classe tiver uma dezena de campos. Felizmente, IDEs modernas (por exemplo, IntelliJ IDEA, Eclipse, VS Code com plugins) conseguem gerá-los automaticamente.
No IntelliJ IDEA
- Abra a classe, posicione o cursor dentro do corpo da classe.
- Pressione Alt + Insert (ou Code -> Generate...).
- Selecione Getter and Setter.
- Marque os campos desejados e clique em OK.
Voilà! Seus getters e setters aparecerão como por mágica.
No Eclipse
- Abra a classe.
- Clique com o botão direito — Source — Generate Getters and Setters...
- Selecione os campos e clique em OK.
No VS Code (com Java Extension Pack)
- Abra o arquivo da classe.
- Na paleta de comandos (Ctrl+Shift+P), digite Generate getters and setters.
- Siga as instruções.
Evolução do seu aplicativo: encapsulamento em ação
Nas aulas anteriores você construiu um aplicativo simples para armazenar contatos. Agora podemos melhorá-lo, tornando os campos privados e fornecendo acesso apenas por getters/setters.
Antes (mau exemplo):
public class Contact {
public String name;
public String phone;
public int age;
}
Problema: qualquer código pode fazer isto:
Contact c = new Contact();
c.age = -1000; // Agora temos um vampiro na agenda telefônica!
Depois (bom exemplo):
public class Contact {
private String name;
private String phone;
private int age;
public void setAge(int age) {
if (age < 0) {
System.out.println("A idade não pode ser negativa!");
return;
}
this.age = age;
}
public int getAge() {
return age;
}
// Outros getters/setters...
}
Agora é impossível quebrar o objeto de fora por acidente (ou de propósito).
7. Getters/setters para propriedades calculadas e imutáveis
Às vezes o valor não é armazenado em um campo, mas calculado em tempo real:
public class Rectangle {
private int width;
private int height;
public int getArea() {
return width * height;
}
}
Não é preciso setter para a área — ela não pode ser definida diretamente, apenas alterando a largura ou a altura.
8. Getters e setters: erros comuns
Erro nº 1: o getter/setter quebra o encapsulamento.
Se um getter retorna uma referência a um objeto interno mutável (por exemplo, a uma lista), o código externo pode alterá-lo, contornando todas as verificações. Isso mina a ideia de encapsulamento.
Erro nº 2: o setter não valida os dados.
Se o setter simplesmente atribui o valor sem verificá-lo, você pode obter um estado incorreto do objeto (por exemplo, idade negativa ou nome vazio).
Erro nº 3: geração automática de setters para todos os campos.
A IDE pode gerar setters para todos os campos, mas isso nem sempre é correto! Por exemplo, para o identificador (id) um setter não é necessário.
Erro nº 4: lógica complexa em getters/setters.
Getters e setters devem ser simples. Se surgir lógica de negócios complexa neles, é melhor extrair para métodos separados.
Erro nº 5: violar as convenções de nomenclatura.
Se você nomear um getter como fetchName() em vez de getName(), alguns frameworks e bibliotecas não conseguirão reconhecê-lo.
GO TO FULL VERSION