pass parameter expresiones ejemplos closure java lambda closures java-8

parameter - java 8 lambda sample



Java Lambdas y cierres (3)

  • ¿Dónde se escribe el equipo A y el equipo B? ¿O no son (como alguna forma extraña de genéricos)?

La tipificación de destino del uso de Lambda, al igual que las llamadas a métodos genéricos (desde 1.5) y el operador de diamante [no es un] (desde 1.7). Aproximadamente, cuando el tipo al que se aplica el resultado se establece (o se puede inferir) que se utiliza para proporcionar el tipo del tipo base del Método único abstracto (SAM) y, por lo tanto, los tipos de parámetros del método.

Como ejemplo de inferencia de método genérico en 1.5:

Set<Team> noTeams = Collections.emptySet();

Y el operador de diamantes en 1.7:

Set<Team> aTeams = new HashSet<>();

Equipo, equipo, equipo, equipo, equipo, equipo. Incluso amo decir la palabra equipo.

  • ¿Es una lambda un tipo de cierre, o es al revés?

Una lambda es una forma limitada de cierre casi de la misma manera que las clases internas anónimas, pero con algunas diferencias aleatorias para atraparlo:

Lo externo no está oculto por un interior this . Esto significa que el mismo texto en una clase interna lambda y anónima puede significar cosas sutilmente pero completamente diferentes . Eso debería mantener Stack Overflow ocupado con preguntas raras.

Para compensar la falta de interno this , si se asigna directamente a una variable local, entonces ese valor es accesible dentro de la lambda. IIRC (podría verificar, pero no lo haré), en una clase interna anónima, el local estará dentro del alcance y ocultará las variables en un ámbito externo, pero no puede usarlo. Creo que la falta de un inicializador de instancia hace que esto sea mucho más fácil de especificar.

Los campos locales que no se marcan como final pero que podrían serlo, se tratan como si fueran final . Entonces, no están dentro del alcance, pero puedes leerlos (aunque no escribirlos).

  • ¿Qué beneficios me dará esto sobre una función anónima típica?

Una sintaxis más breve. Eso es todo.

Por supuesto, el resto de la sintaxis de Java es tan desesperadamente malo como siempre.

No creo que esto esté en la implementación inicial, pero en lugar de implementarse como clases [internas], lambdas puede usar identificadores de método. El rendimiento de los identificadores de método es algo inferior a las predicciones anteriores. La eliminación de las clases debería reducir la huella del bytecode, posiblemente la huella de tiempo de ejecución y, ciertamente, el tiempo de carga de clases. Podría haber una implementación en la que la mayoría de las clases internas anónimas (no Serializable , inicializador estático trivial) no pasaran por el mecanismo de carga de clases pobremente concebido sin ninguna incompatibilidad particularmente notable.

(Espero tener la terminología wrt escondida correcta.)

Escuché que las lambdas vendrán pronto a Java cerca de ti (J8). Encontré un ejemplo de cómo se verán en algún blog:

SoccerService soccerService = (teamA, teamB) -> { SoccerResult result = null; if (teamA == teamB) { result = SoccerResult.DRAW; } else if(teamA < teamB) { result = SoccerResult.LOST; } else { result = SoccerResult.WON; } return result; };

Así que desde el principio:

  • ¿Dónde se teamA y el equipo teamB ? ¿O no son (como alguna forma extraña de genéricos)?
  • ¿Es una lambda un tipo de cierre, o es al revés?
  • ¿Qué beneficios me dará esto sobre una función anónima típica?

La expresión Lambda es solo azúcar sintáctica para implementar una interfaz de destino, esto significa que implementará un método particular en la interfaz a través de una expresión lambda. El compilador puede inferir los tipos de los parámetros en la interfaz y es por eso que no necesita definirlos explícitamente en la expresión lambda.

Por ejemplo:

Comparator<String> c = (s1, s2) -> s1.compareToIgnoreCase(s2);

En esta expresión, la expresión lambda evidentemente implementa un Comparator de cadenas, por lo tanto, esto implica que la expresión lambda es azúcar sintáctica para implementar la compare(String, String) .

Por lo tanto, el compilador puede asumir con seguridad que el tipo de s1 y s2 es String .

El tipo de interfaz de destino proporciona toda la información que el compilador necesita para determinar cuáles son los tipos reales de los parámetros lambda.

Briant Goetz, Java Language Architect en Oracle Corportion ha publicado un par de artículos del trabajo en curso en JDK 8 Lambdas. Creo que las respuestas a sus preguntas están ahí:

Este segundo artículo explica cómo se implementan las expresiones lambda en el nivel de bytecode y puede ayudarte a profundizar en los detalles de tu segunda pregunta.


Consulte esta página para obtener una versión completa de ese ejemplo (sin embargo, las partes relevantes se muestran a continuación).

Los tipos se deducen de la interfaz de SoccerService y de la enumeración de SoccerResult, que no se muestran en su fragmento:

enum SoccerResult{ WON, LOST, DRAW } interface SoccerService { SoccerResult getSoccerResult(Integer teamA, Integer teamB); }

El beneficio (de lambdas versus clases estándar anónimas) es solo una reducción de la verbosidad:

(x, y) => x + y

versus algo así como:

new Adder() { public int add(int x, int y) { return x + y; } }

Para la diferencia entre un cierre y una lambda, vea esta pregunta .