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

javax.swing.JPasswordField

javax.swing.JList