Os atributos de uma classe muito raramente são públicos. Um atributo público pode ser modificado a partir de qualquer ponto do programa e a classe não tem nenhum controle sobre as alterações em seu conteúdo e portanto não pode garantir sua validade. Tornar um atributo público significa abrir mão do controle sobre esse atributo e isso vai completamente contra toda a filosofia e o objetivo da POO. Então o acesso direto aos atributos deve sempre ser restrito associando a eles os modificadores private ou protected. Isso impede que o conteúdo dos atributos seja alterado sem o controle da classe.

Por outro lado, atributos não são constantes e pode haver a necessidade de modificar seu conteúdo. Então deve existir uma maneira permitir a alteração do conteúdo dos atributos por entidades externas à classe, desde que a classe tenha controle suficiente sobre essa alteração para poder garantir a validade do atributo.

A maneira de resolver essa situação é criar métodos especializados em dar um acesso controlado aos atributos. Estes métodos são chamados de getters e setters. O get de um atributo retorna o seu conteúdo e o set permite sua alteração. Note que se o setter de um atributo for o único modo de uma entidade externa à classe modificar seu conteúdo, a classe pode implementar no setter qualquer validação que seja necessária e decidir se aceita ou não a alteração que está sendo feita. Veja o exemplo abaixo, usando a classe Pessoa.

Exemplo:
public class Pessoa {
 private String nome;
 private int idade;
 
 // Construtor
 public Pessoa(String vNome, int vIdade) {
 nome = vNome;
 idade = vIdade;
 }
 
 // Getters
 public String getNome() {
 return nome;
 }
 
 public int getIdade() {
 return idade;
 }
 
 // Setters
 public void setNome(String value){
 if(value != null) nome = value;
 }
 
 public void setIdade(int value){
 if(value >= 0) idade = value;
 }
 
} // classe Pessoa
 
No exemplo acima, os dois atributos da classe são privados, portanto não é possível ter acesso direto a eles de fora da classe. Apesar disso é possivel que outras classes possam obter o valor dos atributos através dos métodos getNome e getIdade. Caso outra classe precise alterar o valor de algum atributo, isso é possível usando os métodos setNome ou setIdade, desde que as condições impostas pelos métodos sejam satisfeitas. O método setNome não aceita uma string nula (vazia) e o método setIdade não aceita um valor negativo.

Dicas e casos especiais


Use o netbeans: O netbeans sabe como programar getters e setters básicos, então deixe-o fazer isso. No arquivo fonte da classe, clique com o botão direito em qualquer linha dentro da classe, mas fora de qualquer método (por exemplo entre dois métodos), escolha a opção "Inserir código" e depois "Getter e setter". O netbeans irá mostrar uma janela com todos os atributos da classe e então basta selecionar os atributos que o netbeans se encarrega de escrever o código básico dos getters e setters para os selecionados.

Mas cuidado!!! Não vá enfiando getters e setters públicos no programa sem necessidade. Só faça se for realmente necessário e depois de avaliar o impacto sobre o funcionamento da classe. Existem casos em que o atributo não pode ter getters ou setters (pelo menos não públicos), por que isso acaba com os controles internos da classe. Um exemplo típico é uma classe que gerencia uma conta corrente e tem como um de seus atributos o saldo da conta. A classe oferece métodos para depositar e para sacar dinheiro da conta e estes métodos atualizam o valor do saldo. Se o atributo para o saldo tiver um setter, todo esse mecanismo de depósitos e saques perde o sentido. Neste caso o saldo não pode ter um setter.

Uso interno: Alguns atributos podem ser necessários apenas para controle interno da classe e não há motivo para que sejam acessados externamente. Neste caso não é necessário (e nem aconselhável) implementar getters e setters para eles, ou caso sejam implementados, devem ficar com acesso privado ou protegido. Só ofereça getters e/ou setters públicos se isso for realmente necessário.

Read only: Se quiser que algum atributo seja apenas para leitura, basta tornar o setter dele privado e deixar o getter público.

Atributos "virtuais": Getters e setters não precisam necessariamente ter correspondência com os atributos declarados na classe. Considere o getter abaixo para a classe Pessoa:
public class Pessoa {
 
 ...
 
 public String getFaixaEtaria() {
 if(idade < 12) return "Criança";
 else
 if(idade < 18) return "Adolescente";
 else
 return "Adulto";
 }
 
} // classe Pessoa
 
Neste exemplo, não existe realmente um atributo para a faixa etária da pessoa, essa informação é calculada a partir da idade. Mas as outras classes não sabem e não precisam saber disso.

Armadilha: Falando em informações calculadas, um erro bastante comum para quem está iniciando na POO é declarar atributos cujo conteúdo é resultado de um cálculo ou processo feito a partir de outros atributos. Se uma informação é resultado de um cálculo ou processo, então deve ser implementado um método que retorne essa informação e não armazená-la em um atributo, assim como foi feito no exemplo anterior para a faixa etária.

Links recomendados: