2015-09-29 1 views
4

oracle Java 8 documentation définit 4 types de références de méthode que vous pouvez utiliser à la place des expressions Lambda. Ce que j'essaie de comprendre, c'est le type de référence de méthode décrit comme: "Référence à une méthode d'instance d'un objet arbitraire d'un type particulier" qui s'écrit ContainingType::methodName.Comment une méthode "référence à une méthode d'instance d'un objet arbitraire d'un type particulier" résout-elle l'objet arbitraire?

Je ne sais pas si je manque quelque chose, mais pour moi, il semble plus comme: « Référence au premier paramètre de la méthode abstraite de l'interface fonctionnelle, en supposant qu'il est de type ContainingType ». J'ai essayé de trouver des exemples où cet 'objet arbitraire' est le deuxième paramètre, mais bien sûr il ne compile pas.

Existe-t-il une référence officielle sur la façon dont cet objet est résolu par le compilateur? Suis-je bien entendu que:

  1. L'objet arbitraire doit être le 1er paramètre de la méthode abstraite de l'interface fonctionnelle.
  2. La signature de la référence de méthode doit être la même que celle de la méthode abstraite de l'interface fonctionnelle, sans le premier paramètre.

donc une interface fonctionnelle avec méthode abstraite A method(B b, C c, D d) ne peut être transmis méthode d'instance ou références x::methodImplB::methodImpl. Il n'y a aucun moyen que je puisse passer C::methodImpl par exemple, où ce serait une instance de la classe C avec sa signature A methodImpl(B b, D d).

Y at-il d'autres cas qui me manquent, ce qui pourrait être la raison pour laquelle Oracle a écrit ceci d'une manière si ambiguë?

+1

'B :: methodImpl' référence une méthode d'instance arbitraire' b' de type 'B'. Le 'b' arbitraire sera passé à la fonction en tant que 1er paramètre. – ZhongYu

+0

Que faire si la méthode d'instance dans 'B' a la signature suivante:' Une méthodeImpl (C c) '(manquant l'argument D) va-t-elle fonctionner, ignorant le dernier argument de l'expression lambda? Comme lorsque nous faisons '(B b, C c, D d) -> b.methodImpl (c)'? Ou la signature doit-elle correspondre exactement? – jbx

+1

Pensez à une méthode d'instance en tant que méthode statique, avec un 1er paramètre supplémentaire. Donc 'A methodImpl (C c)' est un peu comme 'static A methodImpl (B b, C c)'. Par conséquent, la référence à cette méthode est compatible avec les fonctions de forme '(B, C) -> A' – ZhongYu

Répondre

6

Non, votre compréhension est correcte. La documentation que vous avez liée implique (mais n'insiste pas suffisamment) que, étant donné une interface fonctionnelle qui attend les arguments a1, a2, a3, ..., une référence de méthode de ce type est équivalente à un lambda qui appelle a1.namedMethod(a2, a3, ...).

Notez qu'une définition concrète comme cela est nécessaire pour des raisons de cohérence - étant donné l'exemple sur la documentation liée d'une interface fonctionnelle avec deux String arguments (String s1, String s2), comment voulez-vous déterminer si le comportement serait s1.doThing(s2) ou s2.doThing(s1) autrement?

Vous pouvez trouver ce spécifié précisément dans the JLS:

Si la déclaration de compilation est une méthode d'instance, puis les arguments à l'expression d'invocation de méthode (le cas échéant) sont les paramètres formels deuxième et les suivants de la méthode d'invocation. Sinon, les arguments de l'expression d'invocation de la méthode sont les paramètres formels de la méthode d'invocation.

+0

Merci pour votre réponse. Oui bien sûr, si les arguments de la méthode sont '(String s1, String s2)' il correspondrait au premier. Mais alors j'ai commencé à penser que si les arguments où '(Integer i, String s)', il correspondrait encore à une référence de méthode comme 'String :: method' où' method' prend un '(Integer)'? Il n'était pas clair ce que «arbitraire» voulait dire, était-ce le premier qui correspondait au type? Était-ce le premier argument? Et si la méthode abstraite avait '(a1, a2, a3)' et que la référence de la méthode avait les arguments '(a1, a2)', cela fonctionnerait-il encore, ignorant 'a3'? Rien n'est mentionné clairement dans le tutoriel d'Oracle. – jbx

+0

Juste pour clarifier le dernier cas, l'expression lambda suivante '(B b, C c, D d) -> b.methodImpl (c)' ne peut pas être remplacée par une référence de méthode 'B :: methodImpl' right? (c'est-à-dire que la méthode abstraite de l'interface fonctionnelle a 3 paramètres, mais la référence de méthode a 2, de sorte que la dernière est juste inutilisée). Vous devez l'écrire en entier dans ce cas, n'est-ce pas? – jbx