Java, Clase Genérica

Antes de Java 5 cuando introducíamos objetos en una colección, estos se guardaban como objetos de tipo Object, aprovechando el polimorfismo para poder introducir cualquier tipo de objeto en la colección. Esto nos obligaba a hacer un casting al tipo original al obtener los elementos de la colección.


import java.util.ArrayList;
import java.util.List;

public class Coleccion {
public static void main(String[] args) {
List lista = new ArrayList();
lista.add("Colección A");

String cadena = (String) lista.get(0);
System.out.println(cadena)
}
}

Esta forma de trabajar no solo nos ocasiona tener que escribir más código innecesariamente, sino que es propenso a errores porque carecemos de un sistema de comprobación de tipos. Si introdujéramos un objeto de tipo incorrecto el programa compilaría pero lanzaría una excepción en tiempo de ejecución al intentar convertir el objeto en String:

import java.util.ArrayList;
import java.util.List;

public class Ejemplo {
public static void main(String[] args) {
   List lista = new ArrayList();
   lista.add(22);

   String cadena = (String) lista.get(0);
   System.out.println(cadena);
   }
}

Podríamos utilizar el operador instanceof para comprobar el tipo del objeto antes de hacer el casting o antes de introducirlo en la colección, pero es poco elegante, añade aún más código a escribir, y no nos evitaría tener que hacer el casting.

Desde Java 5 contamos con una característica llamada generics que puede solventar esta clase de problemas. Los generics son una mejora al sistema de tipos que nos permite programar abstrayéndonos de los tipos de datos, de forma parecida a los templates o plantillas de C++ (aún mejor).

Gracias a los generics podemos especificar el tipo de objeto que introduciremos en la colección, de forma que el compilador conozca el tipo de objeto que vamos a utilizar, evitándonos así el casting. Además, gracias a esta información, el compilador podrá comprobar el tipo de los objetos que introducimos, y lanzar un error en tiempo de compilación si se intenta introducir un objeto de un tipo incompatible, en lugar de que se produzca una excepción en tiempo de ejecución.

El siguiente ejemplo clarifica la utilización de generics. Para empezar con ello vamos a construir  la clase Reporte que es una clase sencilla que nos permitirá almacenar objetos de varios tipos.

1

Esta clase tendrá un límite  de clases a almacenar. Alcanzando el límite no se podrán agregar más. Este es el código:

package com.mvit.reporte;

import java.util.ArrayList;
import java.util.Iterator;

@SuppressWarnings("rawtypes")
public class Reporte implements Iterable {

private ArrayList lista= new ArrayList();
   private int tope;

   public Reporte(int tope) {
   super();
   this.tope = tope;
  }
@SuppressWarnings("unchecked")
   public void add(Object objeto ) {
   if (lista.size()<=tope)
      lista.add(objeto);
   else
      throw new RuntimeException("limite máximo de Reporte");
   }

   public Iterator iterator() {
      return lista.iterator();
   }
}

Se tiene las siguientes clases para utilizar el contenedor del reporte.

1

package com.mvit.servicios;

public class Financiero {

   private String informe;

   public String getMarca() {
      return informe;
   }

   public void setMarca(String marca) {
      this.informe = marca;
   }

   public Financiero(String marca) {
     super();
     this.informe = marca;
   }

}

package com.mvit.servicios;

   class Contable {
      private String nombre;

      public String getNombre() {
        return nombre;
      }

      public void setNombre(String nombre) {
        this.nombre = nombre;
     }

     public Contable(String nombre) {
        super();
        this.nombre = nombre;
     }
}

Este es el programa aplicativo que utiliza los reportes a desplegar:

import java.util.ArrayList;
import java.util.List;

public class Ejemplo {
   public static void main(String[] args) {
      List lista = new ArrayList();
     lista.add(22);

     String cadena = (String) lista.get(0);
     System.out.println(cadena);
   }
}

El programa funcionará correctamente, pero nos podremos dar cuenta que resulta bastante poco amigable la estructura if /else en la cual se chequean cada uno de los tipos a la hora de presentarlo por pantalla.

Java Generics

Para solventar este problema existe el concepto de Genérica .Este tipo de permite definir un Reporte (en este ejemplo) de un tipo concreto. Puede ser un  Reporte Financiero o un Reporte Contable pero NO de las dos cosas  a la vez .Esto en un principio puede parecer poco flexible pero si nos ponemos a pensar cuando programamos solemos imprimir una lista de Reportes Financieros  o una lista de Reportes Contables, más  no una lista mixta. Así pues el enfoque parece razonable. Este es el código fuente:

package com.mvit.reporte;

import java.util.ArrayList;
import java.util.Iterator;

public class ReporteGenerics<T> implements Iterable<T> {

   private ArrayList<T> lista= new ArrayList<T>();
   private int maximo;

   public ReporteGenerics(int maximo) {
      super();
      this.maximo = maximo;
   }

   public void add(T objeto ) {
     if (lista.size()<=maximo)
        lista.add(objeto);
     else
       throw new RuntimeException("limite máximo de Reporte");
   }

    public Iterator<T> iterator() {
       return lista.iterator();
    }
}

La clase es un poco peculiar ya que al no saber de entrada de qué tipo va a ser el reporte se debe declarar un tipo Genérico T a nivel de clase y que será repetido en cada uno de los métodos que lo usen.

1

De esta manera cuando se construye  un objeto de esta clase será el momento de especificar el tipo de Reposte que se busca .En el siguiente ejemplo se elige “Financiero” como tipo de Reporte. De esta manera el Reporte solo admitirá este tipo de objetos.

package com.mvit.app;

import com.mvit.reporte.ReporteGenerics;
import com.mvit.servicios.Financiero;

public class ControlReportesGenerics {

   public static void main(String[] args) {

     /*Observese que el contructor en en la clase ReporteGenerics se
     implemeta con el número máximo de valores a introducir */
     ReporteGenerics<Financiero> financiero= new ReporteGenerics<Financiero>(5);

     Financiero f1= new Financiero("Regulatorio");
     Financiero f2= new Financiero("Cartera");
     Financiero f3= new Financiero("Transferencia");
     Financiero f4= new Financiero("Dólares");

     financiero.add(f1);
     financiero.add(f2);
     financiero.add(f3);
     financiero.add(f4);

     for (Financiero financieroI:financiero)
       System.out.println(financieroI.getInforme());
    }
}

 

 

 

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s