Inferencia tipos Java: El operador diamante
El operador diamante de Java, permite quitarnos cierta verbosidad a la hora de escribir nuestro código
El proyecto de este post los puedes descargar pulsando AQUI.
Intro
El operador diamante es básicamente azúcar sintáctico (syntactic sugar) de Java, que nos va a permitir quitarnos cierta verbosidad a la hora de escribir nuestro código. Esta característica fue incluida en Java 7, por lo que solo podréis usarla en versiones superiores a Java 7.
Ya estaba disponible en métodos
Esta sintaxis ya estaba disponible en los métodos, lo que nos aporta Java 7 es traernos esta tecnología a los constructores.
Si nosotros declarábamos en una clase GenericMehodClass
public class GenericMehodClass {
public <T> void printElement(T element){
System.out.println(element);
}
}
Podemos invocarlo
GenericMehodClass genericMehodClass = new GenericMehodClass();
genericMehodClass.<String>printElement("Hola");
genericMehodClass.<Integer>printElement(5);
Pero el compilador es lo suficientemente inteligente como para saber que si lo que le pasamos es un string, no tenemos que repetírselo, por lo que podemos simplemente decirle:
genericMehodClass.printElement("Hola");
genericMehodClass.printElement(5);
Resultado
Hola 5 Hola 5
Operador diamante
El operador diamante es una mejora en la inferencia de tipos en genéricos, dejando que el compilador sea quien determine el tipo de la clase genérica y no el programador, con el consiguiente ahorro de esfuerzo y tiempo que ello suponía. Además como mucha gente pensaba, no aportaba mucho tener a la derecha y a la izquierda duplicados los tipos.
Con Java 6
//Java 6 style List<String> java6List = new ArrayList<String>();
Con java 7
//Java 7 style List<String> java7List = new ArrayList<>();
De esta manera queda menos verboso, el compilador sabe que java7List va a ser de tipo String al estar declarado en la parte izquierda. Los dos ejemplos hacen exactamente lo mismo.
Declaración de clases genéricas
No solo podemos usar las clases genéricas como List, Map, Set, etc. Podemos crearnos las nuestras propias, además complicando todo lo que queramos. En el siguiente ejemplo vamos a ver que nos podemos declarar una clase genérica que sea de tipo U, conteniendo una lista de tipo U y con un constructor de tipo T
import java.util.ArrayList;
import java.util.List;
public class GenericClass <U> {
List<U> list = new ArrayList<>();
<T> GenericClass(T t) throws NoSuchFieldException {
System.out.println("T: " + t.getClass().getSimpleName());
}
public void add(U element){
list.add(element);
System.out.println("U: " + list.get(0).getClass().getSimpleName());
}
}
Como vemos la podemos instanciar con el operador diamante:
GenericClass<String> genericClass1 = new GenericClass<>(5);
genericClass1.add("Hola");
Si lo ejecutamos nos va a decir:
- T: Integer
- U: String
Ya que hemos dicho que el constructor va a ser Integer, pero la clase String. Sin embargo:
GenericClass genericClass2 = new GenericClass("Hola");
genericClass2.add(5);
Nos dice que el constructor es String, pero la clase Integer.
- T: String
- U: Integer
El ejemplo es rebuscado, es solo para dar una visión de lo que se puede hacer con genéricos en cuanto a inferencia de tipos.
Algunas restricciones
Para poder beneficiarnos de la sintaxis, es obligatorio poner el operador diamante (omitir el tipo a la derecha) siempre que el compilador pueda inferir los tipos del contexto. Recordemos que esto es un avance del compilador que ahora es más “listo”, pero no adivino.
Si volvemos al ejemplo anterior:
Con Java 6
//Java 6 style List<String> java6List = new ArrayList<String>();
Con java 7
//Java 7 style List<String> java7List = new ArrayList<>();
Esa sería la sintaxis correcta, si hacemos
List<String> java7NonDiamondList = new ArrayList();
Nos va a dar un warning
Warning:(26, 43) java: unchecked conversion required: java.util.List found: java.util.ArrayList
Ya que new ArrayList() hace referencia al tipo raw de ArrayList y no a su tipo genérico.
Tener la flexibilidad de tener tipos genéricos, no hace que perdamos el tipado fuerte de Java, por ejemplo, en la lista podemos hacer
java7List.add("Hola");
Pero no podemos hacer (en la misma lista)
java7List.add(5);
Pues nos da el siguiente error:
add (java.lang.String) in List cannot be applied to (int)
Bibliografía
«Inferencia tipos Java: El operador diamante», de Dionisio Cortés en jarroba.com, con licencia Creative Commons Reconocimiento-NoComercial-CompartirIgual 3.0. Obra registrada en Safe Creative.

Te puede interesar
Interface en Java 8 -Método Default- con ejemplos
Aprende qué es el método default de las interfaces en Java 8, cómo añadir comportamiento sin tocar las clases que las implementan y simular herencia múltiple.
Dockerfile avanzado: multietapa, repositorio y trucos
Curso gratis Docker. Trucos expertos de Docker, multilayer, optimizar, mejorar tiempos. Distribución de imágenes en repositorios Docker.


Deja un comentario