Cómo llamar a un constructor desde otro en Java: detalles no obvios que cambiarán su código
¿Alguna vez ha escrito una clase Java con 5 o 6 constructores y ha sentido que se ahoga en la duplicación de código? ¿O, por el contrario, ha mirado código ajeno donde aparece un misterioso this(name, 0, true) y se ha preguntado: «¿Qué magia es esta?».
La pregunta «How do I call one constructor from another in Java?» es una de las más populares en Stack Overflow (miles de visitas y cientos de respuestas). Y no es casualidad. Una operación aparentemente simple —llamar a un constructor— esconde muchos matices que afectan al rendimiento, la legibilidad e incluso la corrección del programa.
En este artículo no solo mostraremos la sintaxis. Analizaremos bajo el capó de la JVM, veremos cómo el compilador maneja estas llamadas y daremos consejos prácticos que serán útiles tanto para principiantes como para desarrolladores experimentados.
¿Por qué llamar a un constructor desde otro? El problema de la duplicación
Imagine que está escribiendo una clase User que tiene campos obligatorios (nombre, email) y opcionales (edad, teléfono). Quiere dar flexibilidad a los usuarios de su API: crear un objeto con el conjunto mínimo de datos o con todos los detalles.
Enfoque incorrecto (sin llamar a un constructor):
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 por defecto this.phone = null; // valor por defecto }
public User(String name, String email, int age) { this.name = name; this.email = email; this.age = age; this.phone = null; // duplicación otra vez }
public User(String name, String email, int age, String phone) { this.name = name; this.email = email; this.age = age; this.phone = phone; }}Aquí asignamos name y email tres veces. Al añadir un nuevo campo, habría que modificar todos los constructores. Esto viola el principio DRY (Don't Repeat Yourself) y aumenta el riesgo de errores.
Enfoque correcto (llamando a un constructor con 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 al constructor más "completo" }
public User(String name, String email, int age) { this(name, email, age, null); // nuevamente delegación }
public User(String name, String email, int age, String phone) { this.name = name; this.email = email; this.age = age; this.phone = phone; }}Ahora toda la lógica de inicialización está en un solo constructor. Los demás simplemente le delegan el trabajo, pasando valores por defecto. Es conciso, fácil de mantener y hay menos probabilidades de olvidar un campo.
Sintaxis para llamar a un constructor: this() y super()
En Java hay dos palabras clave para llamar a constructores:
this(parámetros)— llama a otro constructor de la misma clase.super(parámetros)— llama al constructor de la clase padre.
Regla fundamental: la llamada a this() o super() debe ser la primera instrucción en el constructor. ¿Por qué? Lo veremos más adelante.
Ejemplo con herencia:
class Animal { private String species;
public Animal(String species) { this.species = species; System.out.println("Animal constructor: " + speci