Expresión lambda frente a referencia de método [cerrado]

114

IntelliJ sigue proponiéndome reemplazar mis expresiones lambda con referencias a métodos.

¿Existe alguna diferencia objetiva entre ambos?

Gerard
fuente
4
¡No realmente, no veo ningún objeto! Me parece una llamada estática
Gerard
9
¡Por supuesto! Pero "no encuentras" tampoco ... Es cuestión de gustos, yo estaba más preocupado por aspectos más técnicos. De hecho, como ya dijiste que son iguales, esa es una buena respuesta para mí. De todos modos, como lo propone IntelliJ, supongo que generalmente es más apreciado ver una referencia de método que una lambda (aunque no para mí).
Gerard
15
El código de una expresión lambda se compila en un método sintético, mientras que las referencias a métodos funcionan sin (excepción: construcciones especiales como Type[]::new). La clase anónima generada en tiempo de ejecución será la misma. El JRE no hace ninguna diferencia entre ellos. Por lo tanto, usar una referencia de método le ahorrará un método en su código compilado, por otro lado, no puede detenerse en ellos cuando realice la depuración paso a paso ...
Holger
6
Ahora la pregunta se va a cerrar ... Lástima para todos los usuarios como yo que no conocen la diferencia entre lambdas y referencias, aunque no haya ninguna decisiva. También me pregunto por qué nadie se atrevió a responder eso. Esa es la respuesta correcta para mí.
Gerard
3
Responder a una pregunta cerrada de dos años es probablemente una mala idea, pero para aquellos que REALMENTE LEÍAN la pregunta, esto es lo que dice el tutorial de Oracle ( docs.oracle.com/javase/tutorial/java/javaOO/… ): Las referencias de métodos ... son Expresiones lambda compactas y fáciles de leer para métodos que ya tienen un nombre.
mañana

Respuestas:

187

Permítanme ofrecerles una perspectiva sobre por qué agregamos esta característica al lenguaje, cuando claramente no lo necesitábamos estrictamente (todas las referencias de métodos se pueden expresar como lambdas).

Tenga en cuenta que no hay una respuesta correcta . Cualquiera que diga "use siempre una referencia de método en lugar de una lambda" o "siempre use una lambda en lugar de una referencia de método" debe ser ignorado.

Esta pregunta es muy similar en espíritu a "¿cuándo debo usar una clase con nombre frente a una clase anónima"? Y la respuesta es la misma: cuando lo encuentre más legible . Ciertamente, hay casos que son definitivamente uno o definitivamente el otro, pero hay una gran cantidad de grises en el medio, y se debe usar el juicio.

La teoría detrás de las referencias de métodos es simple: los nombres importan . Si un método tiene un nombre, entonces referirse a él por su nombre, en lugar de por una bolsa imperativa de código que en última instancia simplemente se da la vuelta y lo invoca, es a menudo (¡pero no siempre!) Más claro y legible.

Los argumentos sobre el desempeño o sobre contar personajes son en su mayoría pistas falsas, y debes ignorarlas. El objetivo es escribir un código que sea claro como el cristal de lo que hace. Muy a menudo (¡pero no siempre!) Las referencias de método ganan en esta métrica, por lo que las incluimos como una opción, para ser utilizadas en esos casos.

Una consideración clave sobre si las referencias de método aclaran u ofuscan la intención es si es obvio por el contexto cuál es la forma de la función que se representa. En algunos casos (p. Ej. map(Person::getLastName), Está bastante claro por el contexto que se requiere una función que mapee una cosa a otra, y en casos como este, las referencias de método brillan. En otros, el uso de una referencia de método requiere que el lector se pregunte de qué tipo de la función se está describiendo; esta es una señal de advertencia de que una lambda podría ser más legible, incluso si es más larga.

Finalmente, lo que hemos descubierto es que la mayoría de las personas al principio se alejan de las referencias de métodos porque se sienten aún más nuevas y extrañas que las lambdas, por lo que inicialmente las encuentran "menos legibles", pero con el tiempo, cuando se acostumbran a la sintaxis, generalmente cambian su comportamiento y gravitan hacia referencias de métodos cuando pueden. Por lo tanto, tenga en cuenta que su propia reacción inicial subjetiva "menos legible" casi con seguridad implica algún aspecto de sesgo de familiaridad, y debe darse la oportunidad de sentirse cómodo con ambos antes de emitir una opinión estilística.

Brian Goetz
fuente
25
@Gerard Gracias, hubiera sido una mejor respuesta.
Yassin Hajaj
3
@Gerard Parece que Brian está diciendo "No, no lo hay"
dj18
Brian, obtengo resultados diferentes usando una referencia de método y una lambda para el mismo método. ¿No deberían ser intercambiables?
Michel Feinstein
@mFeinstein Para cada referencia de método, hay una lambda equivalente (que puede que esté usando o no). ¿Publicar el código como una pregunta?
Brian Goetz
Quiero, pero me temo que el código puede ser demasiado grande, ya que es un Android LiveData, dentro de un Fragment, que convertí a un Eventque se activa por un ViewModel... y el comportamiento diferente ocurre cuando Android vuelve al mismo Fragment... .así que me está costando simplificarlo para una pregunta
Michel Feinstein
10

Las expresiones lambda largas que constan de varias declaraciones pueden reducir la legibilidad de su código. En tal caso, extraer esas declaraciones en un método y hacer referencia a ellas puede ser una mejor opción.

La otra razón puede ser la reutilización . En lugar de copiar y pegar su expresión lambda de pocas declaraciones, puede construir un método y llamarlo desde diferentes lugares de su código.

ovunccetina
fuente
3
Compare: houses.map(House::getName)y houses.map(h -> h.getName()). La lambda toma dos caracteres menos. Es cierto que el tipo no es explícito, pero cualquier IDE te lo diría, y además, se deben usar lambdas cuando el tipo es obvio. Podría estar de acuerdo con usted con la reutilización, pero las lambdas son precisamente pequeñas, por lo que pueden encadenarse en lugar de crear grandes métodos específicos. En ese sentido, los métodos pequeños son más reutilizables que algunos métodos grandes y complejos, y debido a la claridad de las lambdas (y hasta cierto punto, la verbosidad) aún son fáciles de leer.
Gerard
11
Estoy con Gerald. La legibilidad en realidad se ve afectada cuando abandona el código, por lo que debe saltar a él para seguir leyendo y luego retroceder. Usted quiere tener todo el código correspondiente en el mismo lugar. Además, Housees un ejemplo muy benigno; que tal ThreeStoryRedBrickHouseWithBlueDoors. Prefiero referencias de método para lambdas de múltiples argumentos y, a veces, para enfatizar que el lambda se trata solo de una única llamada de método. Hay menos problemas con una referencia de método: podría escribir mal el argumento en el sitio de uso, refiriéndose accidentalmente a una variable del alcance externo, etc.
Marko Topolnik
@Gerard No estoy de acuerdo con tu primera afirmación. Si usa bien los nombres de métodos que describen y si extrae grandes pilas de código, mover el código mejora la legibilidad. Si usa nombres de métodos de ofuscación, estoy de acuerdo con usted.
Torsten