1. Sintaxis de la sobrecarga de constructores
En la vida real rara vez todos los objetos se crean de la misma manera. Imagina la clase Person (Persona). A veces necesitamos crear a una persona con solo su nombre. A veces — con nombre y edad. Y a veces — no sabemos nada; que todo quede por defecto. Sería extraño obligar al usuario de la clase a indicar siempre todos los parámetros, incluso cuando no los necesita.
Sobrecarga de constructores es una forma de dar al usuario de la clase la opción de qué parámetros quiere indicar al crear un objeto y cuáles dejar por defecto. Esto hace que la clase sea flexible y fácil de usar.
Analogía:
En un taller de diseño se construyen coches. Algunos piden el equipamiento básico (sin aire acondicionado, solo volante y ruedas), otros quieren «lujo» (con asientos calefactables, Wi‑Fi y que el coche conduzca solo). Pero el coche — sigue siendo la misma clase; ¡solo hay distintas formas de montarlo!
La sobrecarga es cuando en una misma clase se declaran varios constructores, pero con diferentes parámetros (distinto número, tipo u orden de parámetros). Todos ellos se llaman igual que la clase y no tienen tipo de retorno.
Ejemplo: clase con constructores sobrecargados
public class Person {
String name;
int age;
// Constructor sin parámetros (por defecto)
public Person() {
this.name = "Desconocido";
this.age = 0;
}
// Constructor con un parámetro
public Person(String name) {
this.name = name;
this.age = 0;
}
// Constructor con dos parámetros
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
Ahora podemos crear objetos de diferentes maneras:
Person p1 = new Person(); // nombre = "Desconocido", edad = 0
Person p2 = new Person("John"); // nombre = "John", edad = 0
Person p3 = new Person("Alice", 25); // nombre = "Alice", edad = 25
¿Cómo sabe Java qué constructor usar?
Java se fija en la cantidad y los tipos de los argumentos que pasas después de new. Si escribes new Person("John"), el compilador busca un constructor con un parámetro de tipo String. Si escribes new Person("Alice", 25), necesita un constructor con parámetros String e int.
2. Llamar a un constructor desde otro: this(...)
A veces, al sobrecargar constructores, se da la situación de que parte del código se repite. Por ejemplo, quieres que todos los constructores establezcan obligatoriamente el nombre, y que la edad, si no se indica, sea cero. Para no copiar la misma lógica en cada constructor, puedes llamar a un constructor desde otro con la palabra clave this(...).
Ejemplo
public class Person {
String name;
int age;
// Constructor con dos parámetros
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// El constructor con un parámetro llama a otro constructor
public Person(String name) {
this(name, 0); // llama a Person(String name, int age)
}
// El constructor sin parámetros llama a otro constructor
public Person() {
this("Desconocido", 0);
}
}
public Person(String name) {
this(name, 0); // llama a Person(String, int)
}
Regla importante: ¡La llamada a otro constructor mediante this(...) debe ser la primera línea del constructor!
¿Para qué sirve?
- Reduce la duplicación de código.
- Si decides cambiar la lógica de inicialización (por ejemplo, modificar el valor por defecto), solo tendrás que cambiarla en un sitio.
- El código se vuelve más limpio y fácil de mantener.
3. Ejemplos prácticos: sobrecarga en una clase real
Supongamos que tenemos la clase Account — una cuenta bancaria. A veces solo sabemos el nombre del propietario, a veces queremos indicar de inmediato el saldo inicial y, otras veces, también la divisa.
Ejemplo de clase con constructores sobrecargados
public class Account {
String owner;
double balance;
String currency;
// Constructor con tres parámetros
public Account(String owner, double balance, String currency) {
this.owner = owner;
this.balance = balance;
this.currency = currency;
}
// Constructor con dos parámetros (divisa por defecto — "EUR")
public Account(String owner, double balance) {
this(owner, balance, "EUR");
}
// Constructor con un parámetro (saldo = 0, divisa = "EUR")
public Account(String owner) {
this(owner, 0.0, "EUR");
}
// Constructor sin parámetros (propietario — "Desconocido", saldo = 0, divisa = "EUR")
public Account() {
this("Desconocido", 0.0, "EUR");
}
public void printInfo() {
System.out.println(owner + ": " + balance + " " + currency);
}
}
Uso
public class Main {
public static void main(String[] args) {
Account acc1 = new Account("David", 1000, "USD");
Account acc2 = new Account("Elena", 500);
Account acc3 = new Account("Robert");
Account acc4 = new Account();
acc1.printInfo(); // David: 1000.0 USD
acc2.printInfo(); // Elena: 500.0 EUR
acc3.printInfo(); // Robert: 0.0 EUR
acc4.printInfo(); // Desconocido: 0.0 EUR
}
}
¿Por qué es útil?
- Permite crear objetos con distintos niveles de detalle.
- No es necesario indicar todos los parámetros cada vez (especialmente si a menudo son los mismos).
- Es fácil ampliar la clase: si aparece un nuevo parámetro, puedes añadir otro constructor.
4. Errores típicos al sobrecargar constructores
Error n.º 1: confusión con los tipos y el orden de los parámetros.
Si tienes dos constructores — Person(String name, int age) y Person(int age, String name) — el compilador los diferenciará, pero para el usuario de la clase puede ser muy confuso. Es mejor evitar estas situaciones.
Error n.º 2: falta de constructor por defecto.
Si solo declaras constructores con parámetros y luego intentas crear un objeto sin parámetros, obtendrás un error de compilación. Añade siempre un constructor sin parámetros si lo necesitas.
Error n.º 3: intentar llamar a otro constructor no en la primera línea.
La llamada this(...) siempre debe ser la primera línea del constructor. Si escribes algo antes, habrá un error de compilación.
Error n.º 4: bucle en las llamadas de constructores.
Si un constructor se llama a sí mismo (directa o indirectamente a través de una cadena), esto provocará un error de compilación debido a la recursión infinita.
Error n.º 5: campos no inicializados.
Si te olvidas de inicializar algún campo en el constructor (o en la cadena de llamadas), el objeto puede quedar en un estado incorrecto. Comprueba que todos los campos tengan valores coherentes tras crear el objeto.
GO TO FULL VERSION