domingo, 30 de octubre de 2016

Generics en Java

Creo que este tema esta más que entendido por los seguidores, pero siempre hay gente nueva dispuesta a aprender.

Cualquier lenguaje de tipado estático tiene un problema y es que dada una estructura de datos generica, debemos programarla n veces como n sea el tipo de datos que queramos usarla.

Una posible solución es tipar esta estructura a object, esto trae con sigo ciertos problemas.

  • Se pierde la seguridad por tipo.
  • Debemos castear al tipo de la estructura cada vez que consultemos un elemento:

List list = new ArrayList();
list.add("hello");
String s = (String) list.get(0);

A partir de java 5 se introduce el concepto de clases genéricas. Permiten utilizar y programar estructuras genéricas, las cuales  se les indica el tipo:

List<String> list = new ArrayList<String>();
list.add("hello");
String s = list.get(0);   // no cast

Entre las ventajas podemos nombrar:

  • Chequeo de tipos
  • Se elimina la necesidad de casteos.
  • Posibilidades  de utilizar y programar algoritmos y estructuras genéricas 
  • Es muy utilizado en Framework de colecciones de java. 

Podemos generar clases genericas: 

public class Box<T> {
    // T stands for "Type"
    private T t;
    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

Donde T es el tipo de nuestra clase genérica. Si queremos utilizar esta clase para un tipo determinado:

Box<Integer> integerBox = new Box<Integer>();
integerBox.set(45);
Integer nro = integerBox.get();

Y con el operador diamante: 

Box<Integer> integerBox = new Box<>();
integerBox.set(45);
Integer nro = integerBox.get();

Como ven el operador diamante, no es más que no decirle el tipo cuando instancio la clase, porque el compilador lo puede inferir de la declaración. Es eso y un poco de marketing. 

Veamos otro ejemplo: 

public interface Pair<K, V> {
    public K getKey();
    public V getValue();
}

public class OrderedPair<K, V> implements Pair<K, V> {
    private K key;
    private V value;
    public OrderedPair(K key, V value) {
          this.key = key;
          this.value = value;
    }

    public K getKey() { return key; }
    public V getValue() { return value; }
}

Pair<String, Integer> p1 = new OrderedPair<String, Integer>("Even", 8);
Pair<String, String>  p2 = new OrderedPair<String, String>("hello", "world");
OrderedPair<String, Box<Integer>> p = new OrderedPair<>("primes", new Box<Integer>(...));

Y podemos tener métodos genéricos: 

public class Util {
    public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2) {
        return p1.getKey().equals(p2.getKey()) &&
               p1.getValue().equals(p2.getValue());
    }
}

Por ahora eso es todo de generics. 

Dejo link: