Hay un nuevo bombo con las expresiones lambda tan esperadas en Java 8; cada 3 días aparece otro artículo con ellos sobre lo geniales que son.
Por lo que he entendido, una expresión lambda no es más que una clase interna anónima con un único método (al menos en el nivel de código de bytes). Además de esto, viene con otra característica interesante: la inferencia de tipos, pero creo que el equivalente de esto se puede lograr con genéricos en algún nivel (por supuesto, no de una manera tan clara como con las expresiones lambda).
Sabiendo esto, ¿las expresiones lambda traerán algo más que un simple azúcar sintáctico en Java? ¿Puedo crear clases más potentes y flexibles u otras construcciones orientadas a objetos con expresiones lambda que no se puedan construir con las características del lenguaje actual?
fuente
this
intoOuterClass.this
es parte del proceso de quitar el azúcar de las expresiones lambda a una clase anónima.Respuestas:
tl; dr: si bien es principalmente azúcar sintáctico, esa sintaxis más agradable hace que muchas cosas sean prácticas y que solían terminar en interminables e ilegibles líneas de llaves y paréntesis.
Bueno, en realidad es al revés, ya que las lambdas son mucho más antiguas que Java. Las clases internas anónimas con un único método son (fueron) las más cercanas a Java que llegaron a lambdas. Es una aproximación que fue "suficientemente buena" durante algún tiempo, pero tiene una sintaxis muy desagradable.
En la superficie, las lambdas de Java 8 no parecen ser mucho más que azúcar sintáctica, pero cuando miras debajo de la superficie, ves toneladas de abstracciones interesantes. Por ejemplo, la especificación JVM trata una lambda de manera muy diferente a un objeto "verdadero", y aunque puede manejarlos como si fueran objetos, no es necesario que la JVM los implemente como tal.
Pero aunque todo ese truco técnico es interesante y relevante (¡ya que permite futuras optimizaciones en la JVM!), El beneficio real es "solo" la parte sintáctica del azúcar.
Lo que es más fácil de leer:
o:
o (usando un identificador de método en lugar de una lambda):
El hecho de que finalmente pueda expresar de manera concisa lo que anteriormente serían 5 líneas de código (de las cuales 3 son completamente aburridas) trae un cambio real de lo que es práctico (pero no de lo que es posible, concedido).
fuente
List
podría contener cualquier objeto, unList<String>
"solo" puede contener cadenas. Los genéricos agregaron una restricción (¡y la opción de formalizar restricciones!), No una adición en el poder. Casi todo desde Java 1.1 ha sido el azúcar sintáctico. Y eso no es necesariamente algo malo.List<String>
es solo unList
reparto paraString
agregar alrededor de algunos valores de retorno. Sin embargo, son extremadamente útiles y hacen que el lenguaje sea mucho más conveniente para escribir. Las lambdas son un caso similar.Para Java, sí, no es más que una mejor manera de crear una clase interna anónima. Esto se debe a la decisión fundamental en Java de que cada bit de código de bytes tiene que vivir dentro de una clase específica, que no se puede cambiar ahora después de décadas de código heredado a tener en cuenta.
Sin embargo, de eso no se tratan realmente las expresiones lambda. En los formalismos donde son conceptos nativos en lugar de una contorsión de subirse al carro, las lambdas son bloques de construcción fundamentales; Tanto su sintaxis como la actitud de las personas hacia ellos son muy diferentes. El ejemplo de una función recursiva anónima creada exclusivamente a partir de lambdas en Estructura e interpretación de programas de computadora es capaz de cambiar toda su concepción de la computación. (Sin embargo, estoy bastante seguro de que la forma de aprender a programar es simplemente esotérica para convertirse en una historia de éxito convencional).
fuente
Sí, es solo un azúcar sintáctico, en el sentido de que en cualquier lugar donde escriba un lambda, puede volver a escribir esa expresión como una expresión de clase interna anónima con un método, donde la clase implementa la interfaz funcional inferida para el contexto del lambda, y sería exactamente equivalente semánticamente. Y puede hacer esto simplemente reemplazando la expresión lambda con la expresión de clase anónima, sin cambiar ninguna otra expresión o línea de código.
fuente
this
será necesario convertirloOuterClass.this
. Eso no contradice lo que dije: cada expresión lambda se puede convertir en una expresión de clase anónima semánticamente equivalente sin alterar nada fuera de esa expresión . No dije que el interior no cambiaría.this
en lambda es parte del azúcar sintáctico, y no es una diferencia en la semántica. Y sobre las diferencias en la implementación, implementación! = Semántica. Sobre las diferencias en la identidad del objeto; la identidad del objeto es extremadamente tangencial a la funcionalidad de lambdas; nadie comprueba la identidad del objeto de las clases lambdas / anon de todos modos porque no es útil.Joachim Sauer ya hizo un buen trabajo respondiendo su pregunta, pero solo insinuó algo que considero importante. Como las Lambdas no son clases, tampoco se compilan como tales. Todas las clases internas anónimas dan como resultado la creación de un archivo .class que a su vez debe cargarlo el ClassLoader. Por lo tanto, usar Lambdas en su lugar no solo hace que su código sea más hermoso, sino que también reduce el tamaño de su código compilado, la huella de memoria de su ClassLoader y el tiempo que toma transferir los bits de su disco duro.
fuente
No, ellos no son.
Otra forma de decirlo es que las lambdas son una forma no orientada a objetos, aunque concisa, de lograr lo mismo que una clase anónima o, mi preferencia, la clase interna lograría de una manera orientada a objetos.
fuente