dimecres, 2 de març del 2016

Lambdas en Java

Java es un lenguaje orientado a objetos de primera clase. Con la excepción del tipo de datos primitivos, todo en Java es un objeto. Hasta una matriz es un objeto. Cada clase crea instancias que son objetos. No hay manera de definir solamente una función / método que permanezca en Java por si mismo. No hay manera de pasar un método como argumento o devolver un cuerpo del método para esta instancia.
Las clases internas anónimas era el recurso habitual para intentar ahorrar código escrito.
En resumen, no es fácil pasar métodos planos en Java como argumentos. A causa de esta limitación, Java 8 añade una función de nivel de lenguaje que se llama Expresiones Lambda.
Un lenguaje funcional ofrece un cierre, que tiene bastantes ventajas sobre la manera tradicional de escribir aplicaciones. Un cierre es una función o referencia a una función, junto con el entorno de referencia. Una tabla que guarda una referencia de cada una de las variables no locales de esta función. Lo más parecido que Java puede proporcionar al cierre son las expresiones lambda. Hay una diferencia significativa entre un cierre y expresión lambda, al menos la expresión Lambda ofrece una buena alternativa al cierre. La diferencia es que las Lambdas no son funciones, sino objetos.

¿Qué son?

Una expresión lambda es como una función anónima. En pocas palabras, se trata de un método sin una declaración, es decir, modificador de acceso, la declaración del valor de vuelta y el nombre.
Es una especie de taquigrafía que le permite escribir un método en el mismo sitio donde se va a utilizar. Especialmente útil en sitios donde se utiliza un método una sola vez, y la definición del método es corta. Esto ahorra esfuerzo de declarar y escribir un método independiente para la clase que contiene.
Las expresiones lambda en Java se escriben utilizando la sintaxis:
(argumentos) → (cuerpo)
Ejemplo


int a, int b) -> { return a + b; }
() -> System.out.println("Hello World");
(String s) -> { System.out.println(s); }
() -> 42
() -> { return 3.1415 }

Estructura

Una expresión lambda puede tener cero, uno o más parámetros.
El tipo de los parámetros puede estar declarado explícitamente o se puede inferir a partir del contexto, por ejemplo (int a) es lo mismo que (a).
Los parámetros se incluyen entre paréntesis y separados por comas, por ejemplo (a,b) o (int a, int b) o (String a, int b, float c).
Los paréntesis vacíos se utilizan para representar un conjunto vacío de parámetros, por ejemplo () → 42
Cuando hay un único parámetro, si su tipo es inferido, no es obligatorio el uso de paréntesis. Por ejemplo a → return a*a
El cuerpo de las expresiones lambda puede contener cero, una o más declaraciones.
Si el cuerpo de expresiones lambda tiene declaración única, las llaves no son obligatorias y el tipo de retorno de la función anónima es el mismo que el de la expresión corporal.
Cuando hay más de una sentencia en el cuerpo, estos tienen que estar encerrados entre llaves (un bloque de código) y el tipo de retorno de la función anónima es el mismo que el tipo de valor devuelto dentro del bloque del código, o no serán válidas si no devuelve nada.

Interfaces funcionales

En Java, una interfaz es un clasificador sin métodos definidos ni atributos declarados.
De la misma manera, una interfaz funcional es una interfaz con un único método abstracta declarado en el mismo.
java.lang.Runnable es un ejemplo de una interfaz funcional. Sólo hay un método void run() declarado en la interfaz runnable. De la misma manera la interfaz ActionListener es también una interfaz funcional. Utilizamos las clases internas anónimas para crear instancias de objetos de interfaz funcional. Con expresiones lambda, esto se puede simplificar. Cada expresión lambda se puede asignar implícitamente a una interfaz llamada interfaz funcional. Por ejemplo, podemos crear la referencia de la interfaz runnable como expresión lambda, como podemos ver:
Runnable r = () -> System.out.println("hola món");
Este tipo de conversión la realiza el compilador cuando nosotros no especificamos la interfaz funcional. Por ejemplo:
new Thread( () -> System.out.println("hola món") ).start();
Así en el código anterior, el compilador deduce automaticamente que la expresión lambda puede lanzar la interfaz runnable des del constructor clase:
Thread public Thread(Runnable r){}

@FunctionalInterface
public interface TrabajadorInterfaz{
  public void hacerAlgo();
}
Las interfaces funcionales son interfaces con un solo método diferido. Una vez definida la interfaz funcional, podemos simplemente utilizarla en nuestra API y aprovechar las expresiones lambda.

Cap comentari :

Publica un comentari a l'entrada