Almacenar en Java objetos de diferente tipo en estructuras de datos

COMPARTIR EN REDES SOCIALES

¿ Se pueden almacenar en Java objetos de diferente tipo en estructuras de datos como ArrayList y Arrays estáticos ?

Quizás alguna vez te has preguntado esto, y si lo has hecho, la respuesta es sí, aprovechando la herencia de Java. En Java todo objeto hereda de la clase «Object», no solo las clases que ya están predefinidas en el lenguaje, también nuestras propias clases.

Más adelante escribiremos una serie de entradas destinada a entender la Herencia, el polimorfismo y etc, pero de momento, vamos al lio. Veamos el concepto de que toda clase hereda de Object en Java.

Si todavía no sabes que son los Arrays de memoria estática y los Arrays de memoria dinámica te dejo por aquí 2 entradas donde se explican estas estructuras de datos:

  1. Arrays de memoria estática
  2. Arrays de memoria dinámica o ArrayList

La clase String

Accediendo a la documentación de Java podemos observar la herencia de la clase String de Java.

Herencia de la clase String de Java
Herencia de la clase String de Java

La clase Integer

Ahora veamos la herencia de la clase Integer de Java.

Herencia de la clase Integer de Java
Herencia de la clase Integer de Java

Podríamos seguir así hasta el infinito, pero lo bien cierto es que todo objeto de Java hereda de «Object». Veamos ahora la definición de la clase Object.

La clase Object

Métodos de la clase Object de Java
Métodos de la clase Object de Java

¿ Os suenan de algo los métodos de esta clase ? El método «equals», el método «toString», el método «clone». Son métodos que todo objeto en Java tiene disponible. Vamos a comprobarlo creando una clase de prueba para ver que efectivamente tienen estos métodos disponibles.

Nuestra clase Coche para probar

public class Coche {
	private int numPuertas;
	private String marca;
	private String modelo;
	private int numeroCaballos;
	private int cilindrada;
	private double precio;
	
	public Coche() {
		
	}
	
	public Coche(int numPuertas, String marca, String modelo, int numeroCaballos, int cilindrada, double precio) {
		super();
		this.numPuertas = numPuertas;
		this.marca = marca;
		this.modelo = modelo;
		this.numeroCaballos = numeroCaballos;
		this.cilindrada = cilindrada;
		this.precio = precio;
	}

	public int getNumPuertas() {
		return numPuertas;
	}
	public void setNumPuertas(int numPuertas) {
		this.numPuertas = numPuertas;
	}
	public String getMarca() {
		return marca;
	}
	public void setMarca(String marca) {
		this.marca = marca;
	}
	public String getModelo() {
		return modelo;
	}
	public void setModelo(String modelo) {
		this.modelo = modelo;
	}
	public int getNumeroCaballos() {
		return numeroCaballos;
	}
	public void setNumeroCaballos(int numeroCaballos) {
		this.numeroCaballos = numeroCaballos;
	}
	public int getCilindrada() {
		return cilindrada;
	}
	public void setCilindrada(int cilindrada) {
		this.cilindrada = cilindrada;
	}
	public double getPrecio() {
		return precio;
	}
	public void setPrecio(double precio) {
		this.precio = precio;
	}
	
}

Fijaos que no tiene ningún método «equals», «clone» o «toString» definido. Sin embargo, están disponibles:

Demostración de que el método "equals" está disponible en cualquier clase de Java
Demostración de que el método «equals» está disponible en cualquier clase de Java
Demostración de que el método "equals" está disponible en cualquier clase de Java
Demostración de que el método «toString» está disponible en cualquier clase de Java

¿ Por qué están disponibles estos métodos si nosotros no los hemos implementado en nuestra clase Coche ?

La respuesta es porque toda clase de Java hereda por defecto de la clase «Object», por lo tanto, podemos utilizar este concepto para crear estructuras de datos que contengan objetos de diferente tipo, tanto con memoria estática como con memoria dinámica.

Veamos un ejemplo de un Array de memoria estática

//Definimos los objetos
Coche miCoche = new Coche (5, "Nissan", "Skyline", 240, 2500, 100000);
String miCadena = "Esto es una cadena";
Integer miNumero = 5;
		
//Creamos nuestro Array de memoria estática
Object [] misObjetos = new Object[3];
		
//Insertamos los objetos en el Array
misObjetos[0] = miCoche;
misObjetos[1] = miCadena;
misObjetos[2] = miNumero;
		
//Accedemos a los objetos, utilizando el concepto de Casting
System.out.println(((Coche)misObjetos[0]).getModelo());
System.out.println(((String)misObjetos[1]));
System.out.println(((Integer)misObjetos[2]));

Vamos a explicar qué es lo que hemos implementado:

  1. En las primeras 3 líneas de código creamos los objetos que vamos a almacenar, en este caso, un «Coche», un «String» y un «Integer».
  2. En la siguiente línea creamos nuestro Array de tipo «Object».
  3. Posterior a esto, insertamos nuestros 3 elementos.
  4. Por último, accedemos a cada uno de nuestros objetos y los mostramos por pantalla.

Cabe destacar que es necesario realizar el casting, ya que si no no podríamos acceder a las propiedades de nuestros objetos como en la línea en la que mostramos el modelo del coche.

La salida de nuestro programa

Skyline
Esto es una cadena
5

Veamos ahora un ejemplo con un ArrayList de memoria dinámica

//Definimos los objetos
Coche miCoche = new Coche (5, "Nissan", "Skyline", 240, 2500, 100000);
String miCadena = "Esto es una cadena";
Integer miNumero = 5;

//Creamos nuestro ArrayList
ArrayList<Object> misObjetos = new ArrayList<Object>();
		
//Insertamos nuestros objetos
misObjetos.add(miCoche);
misObjetos.add(miCadena);
misObjetos.add(miNumero);
		
//Mostramos nuestros objetos
System.out.println(((Coche)misObjetos.get(0)).getModelo());
System.out.println(((String)misObjetos.get(1)));
System.out.println(((Integer)misObjetos.get(2)));

Vamos a explicar qué es lo que hemos implementado:

  1. En las primeras 3 líneas de código creamos los objetos que vamos a almacenar, en este caso, un «Coche», un «String» y un «Integer».
  2. En la siguiente línea creamos nuestro ArrayList parametrizado con «Object».
  3. Posterior a esto, insertamos nuestros 3 elementos.
  4. Por último, accedemos a cada uno de nuestros objetos y los mostramos por pantalla.

Cabe destacar que es necesario realizar el casting, ya que si no no podríamos acceder a las propiedades de nuestros objetos como en la línea en la que mostramos el modelo del coche.

La salida de nuestro programa

Skyline
Esto es una cadena
5

¿ Se puede saber que tipo de objeto tenemos almacenado en nuestro ArrayList y en nuestro Array normal ?

La respuesta es sí, utilizando para ello el operador «instanceof». Veamos un ejemplo:

//Definimos los objetos
Coche miCoche = new Coche (5, "Nissan", "Skyline", 240, 2500, 100000);
String miCadena = "Esto es una cadena";
Integer miNumero = 5;
		
//Creamos nuestro Array de memoria estática
Object [] misObjetos = new Object[3];
		
//Insertamos los objetos en el Array
misObjetos[0] = miCoche;
misObjetos[1] = miCadena;
misObjetos[2] = miNumero;
		
//Accedemos a los objetos, utilizando el concepto de Casting
System.out.println(((Coche)misObjetos[0]).getModelo());
System.out.println(((String)misObjetos[1]));
System.out.println(((Integer)misObjetos[2]));

//Averiguamos que tipo de objetos tenemos almacenados		
for (int i = 0; i < misObjetos.length; i++) {
	if (misObjetos[i] instanceof Coche) {
		System.out.println("En la posicion: " + i + " tenemos un coche almacenado");
	}else if (misObjetos[i] instanceof Integer) {
		System.out.println("En la posicion: " + i + " tenemos un Integer almacenado");
	}else if (misObjetos[i] instanceof String) {
		System.out.println("En la posicion: " + i + " tenemos un String almacenado");
	}
}

Podríamos realizar lo mismo con el ejemplo de nuestro ArrayList:

//Definimos los objetos
Coche miCoche = new Coche (5, "Nissan", "Skyline", 240, 2500, 100000);
String miCadena = "Esto es una cadena";
Integer miNumero = 5;

//Creamos nuestro ArrayList
ArrayList<Object> misObjetos = new ArrayList<Object>();
		
//Insertamos nuestros objetos
misObjetos.add(miCoche);
misObjetos.add(miCadena);
misObjetos.add(miNumero);
		
//Mostramos nuestros objetos
System.out.println(((Coche)misObjetos.get(0)).getModelo());
System.out.println(((String)misObjetos.get(1)));
System.out.println(((Integer)misObjetos.get(2)));

//Averiguamos que tipo de objetos tenemos almacenados			
for (int i = 0; i < misObjetos.size(); i++) {
	if (misObjetos.get(i) instanceof Coche) {
		System.out.println("En la posicion: " + i + " tenemos un coche almacenado");
	}else if (misObjetos.get(i) instanceof Integer) {
		System.out.println("En la posicion: " + i + " tenemos un Integer almacenado");
	}else if (misObjetos.get(i) instanceof String) {
		System.out.println("En la posicion: " + i + " tenemos un String almacenado");
	}
}

La salida de nuestro programa en ambos casos

Skyline
Esto es una cadena
5
En la posicion: 0 tenemos un coche almacenado
En la posicion: 1 tenemos un String almacenado
En la posicion: 2 tenemos un Integer almacenado

¿ Cómo funciona el operador instanceof ?

El operador «instanceof» funciona con la siguiente sintaxis:

objetoAComprobar instanceOf tipoDeObjeto, por ejemplo: misObjetos.get(i) instanceof String. Devuelve «true» en caso de que el objeto sea igual al tipo de objeto que estamos comprobando y «false» en caso contrario.

Si os ha gustado el artículo de «Almacenar en Java objetos de diferente tipo en estructuras de datos» dejad un comentario en la caja de comentarios, y si no habéis entendido algo también, ya que os resolveré las dudas a través de este método.


COMPARTIR EN REDES SOCIALES

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *