Como chamar um construtor de outro em Java: detalhes não óbvios que mudarão seu código
Você já escreveu uma classe Java com 5–6 construtores e sentiu que estava se afogando em duplicação de código? Ou, ao contrário, olhou para o código de outra pessoa onde aparecia um misterioso this(name, 0, true) e se perguntou: "Que magia é essa?".
A pergunta "How do I call one constructor from another in Java?" é uma das mais populares no Stack Overflow (milhares de visualizações e centenas de respostas). E não é à toa. Uma operação aparentemente simples – chamar um construtor – esconde muitas nuances que afetam o desempenho, a legibilidade e até a correção do programa.
Neste artigo, não vamos apenas mostrar a sintaxe. Vamos olhar sob o capô da JVM, analisar como o compilador processa essas chamadas e dar dicas práticas que serão úteis tanto para iniciantes quanto para desenvolvedores experientes.
Por que chamar um construtor de outro? O problema da duplicação
Imagine que você está escrevendo uma classe User com campos obrigatórios (nome, email) e opcionais (idade, telefone). Você quer dar flexibilidade aos usuários da sua API: criar um objeto com o conjunto mínimo de dados ou com todos os detalhes.
Abordagem ruim (sem chamar construtor):
public class User { private String name; private String email; private int age; private String phone;
public User(String name, String email) { this.name = name; this.email = email; this.age = 0; // valor padrão this.phone = null; // valor padrão }
public User(String name, String email, int age) { this.name = name; this.email = email; this.age = age; this.phone = null; // duplicação novamente }
public User(String name, String email, int age, String phone) { this.name = name; this.email = email; this.age = age; this.phone = phone; }}Aqui, atribuímos name e email três vezes. Ao adicionar um novo campo, será necessário corrigir todos os construtores. Isso viola o princípio DRY (Don't Repeat Yourself) e aumenta o risco de erros.
Abordagem boa (chamando construtor com this()):
public class User { private String name; private String email; private int age; private String phone;
public User(String name, String email) { this(name, email, 0, null); // delegamos ao construtor mais "completo" }
public User(String name, String email, int age) { this(name, email, age, null); // novamente delegação }
public User(String name, String email, int age, String phone) { this.name = name; this.email = email; this.age = age; this.phone = phone; }}Agora, toda a lógica de inicialização está em um único construtor. Os outros apenas delegam o trabalho a ele, passando valores padrão. Isso é conciso, fácil de manter e reduz as chances de esquecer um campo.
Sintaxe para chamar construtor: this() e super()
Em Java, existem duas palavras-chave para chamar construtores:
this(parâmetros)– chama outro construtor da mesma classe.super(parâmetros)– chama o construtor da classe pai.
Regra fundamental: a chamada this() ou super() deve ser a primeira instrução no construtor. Por quê? Explicaremos em breve.
Exemplo com herança:
class Animal { private String species;
public Animal(String species) { this.species = species; System.out.println("Construtor Animal: " + species);