Se você já aprendeu o básico de classes, atributos e métodos em Java, então você está pronto para dar o próximo passo. Afinal, quando criamos um objeto, nós quase sempre precisamos que ele comece “pronto”, com valores iniciais coerentes.
É exatamente aqui que entra o método construtor em Java. Além disso, você vai aprender também um recurso muito usado no dia a dia: a sobrecarga (overloading) de construtores, que permite criar objetos de formas diferentes, de maneira organizada e legível.
Ao longo deste post, portanto, vamos construir esse conceito com calma, com exemplos práticos, e com uma linguagem bem direta para quem está começando.
Antes de tudo: relembrando o que é uma classe (bem rápido)
Uma classe é como um “molde” que define como serão os objetos daquele tipo.
- Atributos: são as características (dados) do objeto.
Ex.:nome,idade,saldo. - Métodos: são as ações/comportamentos (funções) do objeto.
Ex.:depositar(),sacar(),fazerAniversario().
Por exemplo, uma classe Pessoa pode ter atributos nome e idade. Entretanto, quando você cria um objeto Pessoa, como garantir que ele já nasça com um nome e uma idade válidos? É aí que o construtor faz sentido.
O que é método construtor em Java?
O método construtor em Java é um “método especial” chamado automaticamente quando você cria um objeto com new.
Em outras palavras, ele serve principalmente para:
- Inicializar atributos (definir valores iniciais).
- Garantir consistência do objeto (ex.: não permitir
idadenegativa). - Preparar o objeto para uso imediato (objeto já nasce pronto).
Como reconhecer um construtor?
Um construtor em Java tem estas características:
- Tem o mesmo nome da classe.
- Não tem tipo de retorno (nem
void). - Pode receber parâmetros (ou não).
- É chamado no
new Classe(...).
Exemplo 1: classe sem construtor definido (construtor padrão)
Se você não cria nenhum construtor, o Java fornece um construtor padrão (sem parâmetros) automaticamente.
class Pessoa {
String nome;
int idade;
}
public class Main {
public static void main(String[] args) {
Pessoa p = new Pessoa(); // construtor padrão
System.out.println(p.nome); // null
System.out.println(p.idade); // 0
}
}
Repare que o objeto foi criado, porém os atributos ficaram com valores padrão (null e 0). Assim, embora funcione, nem sempre isso é o que você quer.
Exemplo 2: criando um construtor para inicializar atributos
Agora, vamos criar um construtor que exige nome e idade.
class Pessoa {
String nome;
int idade;
Pessoa(String nome, int idade) {
this.nome = nome;
this.idade = idade;
}
}
public class Main {
public static void main(String[] args) {
Pessoa p = new Pessoa("Ana", 20);
System.out.println(p.nome); // Ana
System.out.println(p.idade); // 20
}
}
O que é this?
this significa “este objeto aqui”. Portanto:
this.nomeé o atributo do objeto.nome(semthis) é o parâmetro recebido no construtor.
Ou seja, this.nome = nome; copia o parâmetro para o atributo.
Construtor pode ter regras (validação)
Além de iniciar valores, você também pode colocar validações.
class Pessoa {
String nome;
int idade;
Pessoa(String nome, int idade) {
this.nome = nome;
if (idade < 0) {
this.idade = 0; // ou poderia lançar erro
} else {
this.idade = idade;
}
}
}
Dessa forma, o objeto fica mais seguro. Inclusive, isso é muito comum em projetos reais.
O que é sobrecarga (overloading) de construtores?
Sobrecarga significa ter mais de um construtor na mesma classe, desde que eles tenham assinaturas diferentes.
Assinatura diferente pode ser:
- Quantidade de parâmetros diferente, ou
- Tipos de parâmetros diferentes, ou
- Ordem dos tipos diferente
Assim, você permite criar objetos de vários jeitos, dependendo da necessidade.
Exemplo 3: sobrecarga de construtores (vários jeitos de criar o mesmo objeto)
Vamos supor uma classe Produto. Às vezes você sabe tudo (nome e preço), mas às vezes você só sabe o nome.
class Produto {
String nome;
double preco;
// Construtor 1: recebe nome e preço
Produto(String nome, double preco) {
this.nome = nome;
this.preco = preco;
}
// Construtor 2: recebe apenas o nome e coloca preço padrão
Produto(String nome) {
this.nome = nome;
this.preco = 0.0;
}
// Construtor 3: sem parâmetros (define valores padrão)
Produto() {
this.nome = "Sem nome";
this.preco = 0.0;
}
}
public class Main {
public static void main(String[] args) {
Produto a = new Produto("Mouse", 99.90);
Produto b = new Produto("Teclado");
Produto c = new Produto();
System.out.println(a.nome + " - " + a.preco);
System.out.println(b.nome + " - " + b.preco);
System.out.println(c.nome + " - " + c.preco);
}
}
Perceba que, agora, você consegue instanciar de maneiras diferentes. Além disso, seu código fica mais flexível, e ao mesmo tempo organizado.
Chamando um construtor a partir de outro: this(...)
Quando existe sobrecarga, é comum você evitar repetição de código. Para isso, você pode chamar um construtor dentro de outro com this(...).
Veja uma versão melhor do exemplo anterior:
class Produto {
String nome;
double preco;
Produto(String nome, double preco) {
this.nome = nome;
this.preco = preco;
}
Produto(String nome) {
this(nome, 0.0); // chama o construtor (String, double)
}
Produto() {
this("Sem nome", 0.0); // chama o construtor (String, double)
}
}
Dessa forma, a lógica de inicialização fica centralizada, e consequentemente o código fica mais fácil de manter.
Importante: this(...) precisa ser a primeira linha do construtor.
Construtor é método? Sim e não (a diferença que cai em prova)
Ele se parece com um método, mas há diferenças importantes:
- Construtor não tem retorno.
- Construtor não tem nome livre (é igual ao nome da classe).
- Construtor serve para criar/inicializar o objeto.
- Métodos comuns executam ações depois que o objeto já existe.
Logo, na prática você “usa” construtores como se fossem métodos, porém o objetivo é diferente.
Erros comuns de iniciantes (e como evitar)
1) Tentar colocar retorno no construtor
Isto está errado:
// ERRADO
Pessoa(String nome) {
return; // até pode ter "return;" sem valor, mas não faz sentido aqui
}
E isto também está errado:
// ERRADO: construtor não pode ter tipo de retorno
void Pessoa(String nome) { }
Se você escreveu void, então você criou um método, e não um construtor.
2) Esquecer que, ao criar um construtor, o padrão some
Quando você cria qualquer construtor, o Java não cria mais o construtor padrão automaticamente.
Então, se você quer permitir new Pessoa() e new Pessoa("Ana", 20), você precisa definir os dois.
Exercício rápido (para praticar)
Crie uma classe Aluno com:
- atributos:
nome,matricula,nota - construtores:
1)Aluno(String nome, String matricula, double nota)
2)Aluno(String nome, String matricula)(nota padrão: 0)
3)Aluno()(nome: “Sem nome”, matrícula: “0000”, nota: 0)
Depois, no main, crie 3 alunos com cada construtor e imprima os dados.
Conclusão
O método construtor é a forma correta de garantir que um objeto já nasça com valores iniciais e pronto para uso. Além disso, com a sobrecarga de construtores, você consegue oferecer várias maneiras de instanciar a mesma classe, deixando seu código mais flexível e mais limpo.
Se você dominar bem isso agora, vai ter muito mais facilidade quando começar a estudar encapsulamento, herança, e polimorfismo, porque construtores aparecem o tempo todo nesses assuntos.
