Java. Genéricos

Descripción

Permiten utilizar tipos concretos en tiempo de compilación con clases que trabajan con tipos arbitrarios. Las clases genéricas tienen tipos parametrizados y el tipo parametrizado se sustituye por un tipo específico. Una vez definido el tipo, la instancia creada solo trabaja con el tipo establecido.

Definición de la interface List:
public interface List<E> extends Collection<E>
Definición de la clase ArrayList:
public class ArrayList<E> extends AbstractList<E>
    implements List<E>, RandomAccess, Cloneable, java.io.Serializable
Definición de la interface Map:
public interface Map<K,V>
Definición de la clase HashMap:
public class HashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable
Ejemplo con List y Map:
// Declarar una lista sin tipo genérico
List lista1 = new ArrayList();
// Al añadir objetos a la lista ella acepta objetos Objetc

// Declarar una lista con un tipo específico
List<String> lista2 = new ArrayList<>();
// Al añadir objetos a la lista, esta solo acepta String

// Map, la clave es un Integer y el objeto asociado es un String
Map<Integer, String> map = new HashMap<>();

A las clases genéricas también se les llama clases parametrizadas. Los tipos de una clase genérica se definen entre <>, separados por coma si hay más de uno.
Ejemplo de una clase parametrizada:
public class Generico1<T> {
    // Propiedad parametrizada
    private T unObjeto;

    public Generico1() {
    }

    public Generico1(T unObjeto) {
        this.unObjeto = unObjeto;
    }

    public T getUnObjeto() {
        return unObjeto;
    }

    public void setUnObjeto(T unObjeto) {
        this.unObjeto = unObjeto;
    }
}

Al crear un objeto Generico1 se le indica entre <> el tipo a utilizar.
Ejemplo de instancias Generico1:
Generico1<String> g1 = new Generico1<>("Hola");
Generico1<Integer> g2 = new Generico1<>(1);

También puede restringirse el tipo a utilizar en las clases genéricas:
public class Generico2<T extends Number> {
    // Propiedades parametrizadas
    private T objeto1;
    private T objeto2;

    public Generico2(T objeto1, T objeto2) {
        this.objeto1 = objeto1;
        this.objeto2 = objeto2;
    }

    public T getObjeto1() {
        return objeto1;
    }

    public void setObjeto1(T objeto1) {
        this.objeto1 = objeto1;
    }

    public T getObjeto2() {
        return objeto2;
    }

    public void setObjeto2(T objeto2) {
        this.objeto2 = objeto2;
    }

    public double sumar() {
        return objeto1.doubleValue() + objeto2.doubleValue();
    }
}

Según la documentación:
The abstract class Number is the superclass of classes BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, and Short.

Instancias de Generico2:
Generico2<Double> g3 = new Generico2<>(12.5d, 12.5d);
System.out.println("Sumar: " + g3.sumar());

Pueden definirse métodos genéricos en una clase:
public class GenericoMetodo {
    
    /**
     * Método genérico que intercambia dos posiciones.
     * @param <MiG>
     * @param vector
     * @param i
     * @param j 
     */
    public static <MiG> void metodogenerico(MiG[] vector, int i, int j){
        System.out.println("Método genérico: ");
        MiG tmp = vector[i];
        vector[i] = vector[j];
        vector[j] = tmp;
    }
    
}

Para hacer uso del método:
String vector[] = {"Uno", "Dos", "tres"};
System.out.println(Arrays.toString(vector));
GenericoMetodo.metodogenerico(vector, 0, 2);
System.out.println(Arrays.toString(vector));

Utilidad

Crear clases capaces de trabajar con objetos genéricos de cualquier tipo o en un rango establecido de tipos. Una vez establecido el tipo se trabaja forma normal y se evita hacer cast al obtener objeto, por ejemplo al obtener un objeto de una lista.

Comentarios

Entradas populares de este blog

Java. Texto de colores en la consola

JSP. 26 Ejemplo MVC simple

JSP. 5 Ejemplo declaraciones, expresiones y scriplet