El constructor en Java

Home >> Programación >> Java


Si estás aprendiendo Java seguramente has oído hablar de los constructores y si has llegado a esta página seguramente sea porque no tienes muy claro qué son o cómo se utilizan.

Pues has llegado al lugar adecuado. Sigue leyendo porque te voy a explicar qué son los constructores en Java, qué tipos existen y cómo se utilizan.

¿Qué es un constructor en Java?

El constructor es un método especial que tienen todas las clases que permite reservar memoria e inicializar objetos de la clase en la que está declarado.

Mira el siguiente código:

String cadena = new String("Hola mundo");

Seguro que has visto eso de new anteriormente.

Y ahora mira este otro código:

public class Rectangulo {
   private float base;
   private float altura;

   public void show(){
       System.out.println("Base: "+base+" Altura: "+altura);
   }
}
public class Main {

   public static void main(String[] args) {
       Rectangulo rectangulo = new Rectangulo();
   }

}

De nuevo aparece aquí el operador new. ¿Qué está ocurriendo exactamente en estos fragmentos de código?

Pues que se está llamando al constructor para instanciar un nuevo objeto.

En el caso de new String(«Hola mundo») se está reservando memoria para una nueva cadena con valor inicial “Hola mundo”. 

En el caso de new Rectangulo() se está instanciando un objeto de la clase Rectangulo con valores iniciales por defecto. 

Como puedes ver, en ambos casos se utiliza el operador new. La finalidad de este operador es invocar al constructor para que realice la reserva de memoria y la inicialización de los objetos.

¿Qué más puedes deducir a partir de estos ejemplos? Seguramente habrás notado que justo a continuación de new escribo el nombre de la clase (String o Rectangulo). Esto se debe a que el constructor siempre tendrá cómo identificador el nombre de la clase a la que pertenece. Si decides asignar otro nombre o identificador al constructor no funcionará, por lo que esta norma de nomenclatura la debes cumplir siempre.

Además de esta norma de nomenclatura debes tener en cuenta otros aspectos a la hora de declarar constructores, como que siempre deben ser públicos y no deben tener ningún tipo de retorno asociado, pero esto ya lo veremos en detalle en los siguientes apartados.

Puede que te hayas dado cuenta de otro detalle. Cuando llamo al constructor de String pongo una cadena entre paréntesis y en el caso del Rectangulo dejo los paréntesis vacíos. Esto se debe a que el primero es un constructor sobrecargado y el segundo es un constructor por defecto, pero no te preocupes por esto, que te lo voy a explicar a continuación.

Tipos de constructores en Java

En Java puedes definir diferentes tipos de constructores dentro de una misma clase gracias a la sobrecarga de métodos.

A continuación te describo algunos de los tipos de constructores que puedes usar en Java y cómo debes declararlos.

Constructor por defecto en Java

Este es el constructor que define Java por defecto. Si no declaras ningún otro constructor dentro de tu clase este constructor estará presente de forma implícita aunque tu no lo definas. 

También se conoce como constructor sin parámetros, puesto que no recibe ningún parámetro en su llamada.

Vamos a ver un ejemplo que siempre se entiende todo muchísimo mejor.

A continuación defino la clase Rectangulo que tiene dos atributos privados de tipo float (base y altura) y un método publico show() que simplemente muestra por pantalla los valores de los dos atributos:

public class Rectangulo {
   private float base;
   private float altura;

   public void show(){
       System.out.println("Base: "+base+" Altura: "+altura);
   }
}

Ahora defino la clase principal Main. Dentro de esta clase está el método main en el cual instancio un objeto de la clase Rectangulo.

Como ya expliqué anteriormente uso el operador new para invocar al constructor, que tiene el mismo identificador que la clase (Rectangulo).

public class Main {
   public static void main(String[] args) {

       Rectangulo rectangulo = new Rectangulo();

   }
}

Seguramente estés pensando, ¿Dónde está el constructor declarado que no lo veo? Claro que no lo ves, porque no lo he definido dentro de la clase. ¿Y entonces por qué funciona? Pues funciona porque Java lo ha definido por mi. Como yo no he declarado ningún constructor dentro de la clase Rectangulo Java ha definido un constructor por defecto de forma implícita.

Aunque Java define el constructor por defecto habrá veces en las que sea necesario que lo definas tú si quieres, por ejemplo, cambiar los valores iniciales que se asignan por defecto. ¿Qué significa esto? Volvamos al ejemplo para que lo entiendas:

Rectangulo rectangulo = new Rectangulo();
rectangulo.show();

He añadido una nueva instrucción justo después de instanciar el objeto Rectangulo dentro del método main. Lo que estoy haciendo es llamar el método show() de la clase Rectangulo, encargado de mostrar por pantalla los valores de los atributos base y altura. ¿Qué crees que se muestra por pantalla?

Se muestra esto:

Base: 0.0 Altura: 0.0

Lo que ha hecho el constructor es asignar a los atributos valor 0 por defecto. Siempre lo hará así cuando se trate de datos primitivos (false en el caso de boolean). Cuando los atributos sean objetos el valor por defecto que asignará será null (por ejemplo si es un String).

Si quieres especificar otros valores por defecto no te queda más remedio que sobrescribir el constructor y definir explícitamente los valores que necesites. 

De esta forma:

public class Rectangulo {
   private float base;
   private float altura;

   //Constructor por defecto
   public Rectangulo() {
       this.base = 5.0f;
       this.altura = 3.0f;
   }
   . . .
}

Fíjate bien en la estructura del constructor:

  • Es público (public) para que se pueda invocar fuera de la case para instanciar objetos.
  • El identificador es el mismo que el de la clase (Rectangulo). Debes escribirlo exactamente igual, incluida la mayúscula.
  • No tiene ningún tipo de retorno (entre public y Rectangulo no hay nada). ¡Cuidado! No lo confundas con void. Si pones void entre public y el identificador ya no es un constructor.
  • No tiene parámetros. Como habrás comprobado entre los paréntesis no hay nada.

Ahora fíjate en el cuerpo del constructor que está encerrado entre las llaves:

this.base = 5.0f;
this.altura = 3.0f;

Lo que hago aquí es especificar los valores por defecto que se deben asignar a los atributos cuando se instancie el objeto. Si no pones nada seguirán siendo 0 o null. Al indicar otros de forma explícita este comportamiento cambia. En este caso el atributo base tomará valor 5 y el atributo altura tomará valor 3.

Compruébalo de nuevo instanciando un objeto y llamando al método show() tal y como hicimos anteriormente:

Rectangulo rectangulo = new Rectangulo();
rectangulo.show();

La salida ahora será esta:

Base: 5.0 Altura: 3.0

Constructor con parámetros en Java

Como vimos en el punto anterior, el constructor por defecto no recibe ningún parámetro e inicializa siempre los objetos con los mismos valores por defecto, pero habrá casos en los que nos interese dinamizar ese comportamiento para poder determinar los valores iniciales en el momento de instanciar los objetos. Aquí es donde cobra sentido el constructor con parámetros o constructor sobrecargado.

Fíjate en este código:

public class Rectangulo {
   private float base;
   private float altura;

   //Constructor con parámetros
   public Rectangulo(float base, float altura) {
       this.base = base;
       this.altura = altura;
   }
   . . .
}

Como puedes ver, ahora el constructor recibe dos parámetros entre paréntesis. Estos parámetros son los valores que se deben asignar por defecto a los atributos del objeto. En este caso son dos float porque los atributos son de ese tipo.

Habrás notado que he usado los mismos identificadores que los atributos para estos parámetros (base y altura). Esto no es obligatorio, puedes llamarlos como quieras.

En el cuerpo del constructor asigno los valores de los parámetros a los atributos:

this.base = base;
this.altura = altura;

Como yo los he llamado igual utilizo el operador this para resolver el ámbito y poder referenciar los atributos del objeto y que se distingan de los parámetros.

Ahora cuando instancies un objeto tendrás que indicar los valores que se asignarán al objeto al llamar al constructor:

Rectangulo rectangulo = new Rectangulo(5.0f, 3.0f);
Rectangulo rectangulo2 = new Rectangulo(6.0f, 4.5f);
rectangulo.show();
rectangulo2.show();

Fíjate que he instanciado dos objetos: rectangulo y rectangulo2. A cada uno le estoy dando unos valores iniciales diferentes (5 y 3 al primero y 6 y 4.5 al segundo).

Si lo ejecutas verás que la salida por pantalla es esta:

Base: 5.0 Altura: 3.0
Base: 6.0 Altura: 4.5

Cada objeto tiene sus propios valores.

¿Y si quiero seguir usando el constructor por defecto? Según está la clase ahora no podrás porque hemos sobrecargado el constructor, por lo que la definición por defecto ya no está disponible.

Si intentas hacer esto te dará un error al intentar instanciar el primer objeto:

Rectangulo rectangulo = new Rectangulo();
Rectangulo rectangulo2 = new Rectangulo(5.0f, 3.0f);

rectangulo.show();
rectangulo2.show();

Para solucionarlo tendrás que definir explícitamente el constructor por defecto junto con el constructor con parámetros. De esa forma tendrás los dos disponibles:

public Rectangulo() {
   this.base = 0.0f;
   this.altura = 0.0f;
}

public Rectangulo(float base, float altura) {
   this.base = base;
   this.altura = altura;
}

Constructor de copia en Java

El constructor de copia no es más que otro constructor sobrecargado. En el apartado anterior veíamos que podíamos sobrecargar el constructor pasando los valores iniciales del objeto a través de los parámetros. 

En este caso haremos exactamente lo mismo con la peculiaridad de que esa información la pasaremos encapsulada en un objeto que será instancia de la misma clase. El constructor inicializará los atributos con los valores de los atributos del objeto pasado como parámetro. Básicamente hará una copia, de ahí el nombre del constructor.

Voy a seguir con la clase Rectangulo que usé en los ejemplos anteriores. Sin eliminar los dos constructores que ya vimos, voy a definir el constructor de copia para así tener los 3 disponibles:

public class Rectangulo {
   private float base;
   private float altura;

   //Constructor por defecto
   . . .

   //constructor con parámetros
   . . .

   //constructor de copia
   public Rectangulo (Rectangulo r) {
       if(r != null) {
          this.base = r.base;
          this.altura = r.altura;
       }
   }

   . . .
}

Fíjate que ahora el parámetro que recibe el constructor es un objeto de la clase Rectangulo. Ese objeto tiene valores iniciales en sus atributos (base y altura).

Como puedes ver, en el cuerpo del constructor asigno el atributo base del objeto r al atributo base del objeto que se está inicializando y lo mismo con el atributo altura.

Además, habrás notado que hago una comprobación previa: if(r != null)

Si el objeto no es null hago la asignación. En este caso el parámetro es un objeto, pero si no ha sido instanciado dará error en ejecución, por lo que es recomendable hacer una comprobación previa. Si el objeto es null y no entra en el if los valores de base y altura serán los valores que Java asigna por defecto (0, false o null dependiendo del tipo), en este caso 0.

¿Cómo invocamos ahora este constructor? Debes tener en cuenta que hará una copia de un objeto Rectangulo, así que necesitas una instancia previa que puedes crear con alguno de los constructores que ya vimos anteriormente:

public class Main {
   public static void main(String[] args) {

       Rectangulo rectangulo2 = new Rectangulo(5.0f, 3.0f);

       Rectangulo rectangulo3 = new Rectangulo(rectangulo2);
       rectangulo3.show();

   }
}

El objeto rectangulo3 será una copia de rectangulo2, por lo que la salida será:

Base: 5.0 Altura: 3.0

¿Y si el objeto que recibe el constructor es null?

public class Main {
   public static void main(String[] args) {

       Rectangulo rectangulo3 = new Rectangulo(null);
       rectangulo3.show();

   }
}

Entonces los valores serán los asignados por defecto:

Base: 0.0 Altura: 0.0

Ejemplo de constructor en Java

Espero que te haya quedado claro con todos los casos anteriores, pero por si acaso, aquí te dejo el ejemplo completo con todos los constructores y las instancias de la clase principal:

Clase Rectangulo:

public class Rectangulo {
   private float base;
   private float altura;

   //Constructor por defecto
   public Rectangulo() {
       this.base = 0.0f;
       this.altura = 0.0f;
   }

   //Constructor con parámetros
   public Rectangulo(float base, float altura) {
       this.base = base;
       this.altura = altura;
   }

   //Constructor de copia
   public Rectangulo(Rectangulo r) {
       if(r != null) {
           this.base = r.base;
           this.altura = r.altura;
       }
   }
  
   //Método que muestra por pantalla los valores de los atributos
   public void show(){
       System.out.println("Base: "+base+" Altura: "+altura);
   }
}

Clase Main:

public class Main {
   public static void main(String[] args) {

       Rectangulo rectangulo = new Rectangulo();
       Rectangulo rectangulo2 = new Rectangulo(5.0f, 3.0f);
       Rectangulo rectangulo3 = new Rectangulo(rectangulo2);

       rectangulo.show();
       rectangulo2.show();
       rectangulo3.show();

   }
}

Los comentarios están cerrados.

Subir ↑