Inferencia tipos Java: El operador diamante


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 declarabamos 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 repetirselo, 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 un 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 genericos, 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)

Referencias

Comparte esta entrada en:
Safe Creative #1401310112503
Inferencia tipos Java: El operador diamante por "www.jarroba.com" esta bajo una licencia Creative Commons
Reconocimiento-NoComercial-CompartirIgual 3.0 Unported License.
Creado a partir de la obra en www.jarroba.com

1 thoughts on “Inferencia tipos Java: El operador diamante”

  1. Consulta. En tu ejemplo public class GenericClass , porque declaras y no …. digo, cual es la que debe declarar la clase, si los metodos utilizan mas de una generica? Gracias!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies

ACEPTAR
Aviso de cookies