Expression Lambda vs référence de méthode [fermé]

114

IntelliJ ne cesse de me proposer de remplacer mes expressions lambda par des références de méthode.

Y a-t-il une différence objective entre les deux?

Gérard
la source
4
Pas vraiment, je ne vois aucun objet! Cela ressemble à un appel statique pour moi
Gerard
9
Bien sûr! Mais "ne trouvez-vous pas" non plus ... C'est une question de goût, j'étais plus préoccupé par des aspects plus techniques. En fait, comme vous l'avez déjà dit, ce sont les mêmes, c'est une bonne réponse pour moi. Quoi qu'il en soit, comme IntelliJ le propose, je suppose qu'il est généralement plus apprécié de voir une référence de méthode qu'un lambda (pas pour moi, cependant).
Gerard
15
Le code d'une expression lambda est compilé en une méthode synthétique tandis que les références de méthode fonctionnent sans (exception: constructions spéciales comme Type[]::new). La classe anonyme générée lors de l'exécution sera la même. Le JRE ne fait aucune différence entre eux. Donc, utiliser une référence de méthode vous fera économiser une méthode dans votre code compilé, d'un autre côté, vous ne pouvez pas vous arrêter à eux lorsque vous effectuez un débogage étape par étape…
Holger
6
Maintenant la question va se fermer ... Dommage pour tous les utilisateurs comme moi qui ne connaissent pas la différence entre lambdas et références, même s'il n'y en a pas de décisif. Je me demande aussi pourquoi personne n'a osé répondre à cela? C'est la bonne réponse pour moi.
Gerard
3
Répondre à une question fermée vieille de deux ans est probablement une mauvaise idée, mais pour ceux qui LIRE RÉELLEMENT la question, voici ce que dit le tutoriel d'Oracle ( docs.oracle.com/javase/tutorial/java/javaOO/… ): Les références de méthode ... sont expressions lambda compactes et faciles à lire pour les méthodes qui ont déjà un nom.
demain

Réponses:

187

Permettez-moi de vous expliquer pourquoi nous avons ajouté cette fonctionnalité au langage, alors que nous n'en avions clairement pas besoin (toutes les méthodes refs peuvent être exprimées en lambdas.)

Notez qu'il n'y a pas de bonne réponse . Quiconque dit "toujours utiliser une méthode ref au lieu d'un lambda" ou "toujours utiliser un lambda au lieu d'une méthode ref" doit être ignoré.

Cette question est très similaire dans l'esprit à "quand dois-je utiliser une classe nommée par rapport à une classe anonyme"? Et la réponse est la même: quand vous le trouvez plus lisible . Il y a certainement des cas qui sont certainement l'un ou certainement l'autre, mais il y a une foule de gris au milieu, et le jugement doit être utilisé.

La théorie derrière les méthodes refs est simple: les noms comptent . Si une méthode a un nom, il est souvent (mais pas toujours!) Plus clair et lisible de s'y référer par son nom, plutôt que par un sac de code impératif qui, finalement, se retourne et l'invoque.

Les arguments sur les performances ou sur le comptage des caractères sont pour la plupart des harengs rouges, et vous devez les ignorer. Le but est d'écrire un code qui soit parfaitement clair. Très souvent (mais pas toujours!) Les références de méthode gagnent sur cette métrique, nous les avons donc incluses en option, à utiliser dans ces cas.

Une considération clé pour savoir si les références de méthode clarifient ou obscurcissent l'intention est de savoir s'il est évident du contexte quelle est la forme de la fonction représentée. Dans certains cas (par exemple, il est map(Person::getLastName)assez clair d'après le contexte qu'une fonction qui mappe une chose à une autre est requise, et dans des cas comme celui-ci, les références de méthode brillent. Dans d'autres, l'utilisation d'une méthode ref oblige le lecteur à se demander quel type de la fonction est en cours de description; c'est un signe d'avertissement qu'un lambda peut être plus lisible, même s'il est plus long.

Enfin, ce que nous avons constaté, c'est que la plupart des gens s'éloignent d' abord des références de méthodes car ils se sentent encore plus récents et plus bizarres que les lambdas, et les trouvent donc initialement "moins lisibles", mais avec le temps, lorsqu'ils s'habituent à la syntaxe, changent généralement de comportement et se tournent vers les références de méthodes quand ils le peuvent. Soyez donc conscient que votre propre réaction subjective initiale «moins lisible» implique presque certainement un certain biais de familiarité, et vous devriez vous donner une chance de vous familiariser avec les deux avant de rendre une opinion stylistique.

Brian Goetz
la source
25
@Gerard Merci aurait été une meilleure réponse.
Yassin Hajaj
3
@Gerard On dirait que Brian dit "Non, il n'y en a pas"
dj18
Brian, j'obtiens des résultats différents en utilisant une référence de méthode et un lambda pour la même méthode. Ne devraient-ils pas être interchangeables?
Michel Feinstein
@mFeinstein Pour chaque méthode ref, il existe un lambda équivalent (que vous pouvez utiliser ou non). Postez le code comme une question?
Brian Goetz
Je veux, mais j'ai peur que le code soit trop gros, car c'est un Android LiveData, à l'intérieur d'un Fragment, que j'ai converti en un Eventqui est déclenché par un ViewModel... et le comportement différent se produit lorsque Android revient au même Fragment. .so j'ai du mal à le simplifier pour une question
Michel Feinstein
10

Les expressions lambda longues constituées de plusieurs instructions peuvent réduire la lisibilité de votre code. Dans un tel cas, extraire ces instructions dans une méthode et y faire référence peut être un meilleur choix.

L'autre raison peut être la réutilisation . Au lieu de copier-coller votre expression lambda de quelques instructions, vous pouvez construire une méthode et l'appeler à partir de différents endroits de votre code.

ovunccétine
la source
3
Comparez: houses.map(House::getName)et houses.map(h -> h.getName()). Le lambda prend deux caractères de moins. Il est vrai que le type n'est pas explicite, mais n'importe quel IDE vous le dirait, et de plus, les lambdas devraient être utilisés lorsque le type est évident. Je suis peut-être d'accord avec vous avec la réutilisabilité, mais les lambdas sont précisément minuscules afin de pouvoir être enchaînées au lieu de créer de grandes méthodes spécifiques. En ce sens, les petites méthodes sont plus réutilisables que certaines méthodes grandes et complexes, et en raison de la clarté de lambdas (et dans une certaine mesure, de la verbosité) elles sont toujours faciles à lire.
Gerard
11
Je suis avec Gerald. La lisibilité souffre en fait lorsque vous sortez du code, vous devez donc y accéder pour continuer à lire, puis revenir en arrière. Vous voulez avoir tout le code pertinent au même endroit. En outre, Houseest un exemple très bénin; qu'en est-il ThreeStoryRedBrickHouseWithBlueDoors. Je préfère les références de méthode pour les lambdas à arguments multiples, et parfois pour souligner que le lambda ne concerne qu'un seul appel de méthode. Il y a moins de mal à se tromper avec une référence de méthode: vous pourriez mal orthographier l'argument au site d'utilisation, faire accidentellement référence à une variable de portée externe, etc.
Marko Topolnik
@Gerard Je ne suis pas d'accord avec votre première déclaration. Si vous utilisez des noms de méthodes bien décrits et si vous extrayez de grandes piles de code, le déplacement du code améliore la lisibilité. Si vous utilisez des noms de méthode obscurcissants, je suis d'accord avec vous.
Torsten