Ich habe das Java 8-Tutorial zu Lambda-Expressionen gelesen und verstehe das Methodenreferenzbeispiel für "Referenz auf eine Instanzmethode eines beliebigen Objekts eines bestimmten Typs" nicht
Im selben Tutorial gibt es ein Beispiel "Verweis auf eine Instanzmethode eines bestimmten Objekts", das aussieht.
%Vor%Ich kann sehen, dass dies funktioniert, weil die Methode compareByName die gleiche Signatur wie Comparator.compare, lambda (a, b) - & gt; myComparisonProvider.compareByName (a, b) benötigt zwei Argumente und ruft eine Methode mit denselben zwei Argumenten auf.
Das Beispiel "Referenz auf eine Instanzmethode eines beliebigen Objekts eines bestimmten Typs" verwendet nun String :: compareToIgnoreCase
%Vor% Die Signatur für diese Methode lautet int compareTo(String anotherString)
und unterscheidet sich von Comparator.compare. Das Tutorial ist nicht sehr klar, scheint aber zu implizieren, dass Sie mit einem Lambda wie (a, b) - & gt; a.compareToIgnoreCase (b) Ich verstehe nicht, wie der Compiler entscheidet, was für den zweiten Parameter von Arrays akzeptabel ist.sort Ich dachte, es ist vielleicht schlau genug zu verstehen, wie man diese Methode aufruft, also habe ich ein Beispiel erstellt.
Kann jemand erklären, warum die oben genannten zwei Arrays.sort nicht kompilieren, obwohl sie Methoden verwenden, die mit der Methode String.compareToIgnoreCase
identisch sind In FakeString
, Ihr compareToIgnoreCase
hat ein einzelnes String
Argument, daher kann es nicht an Stelle von Comparator<String>
kommen, was eine Methode mit zwei String Argumenten erfordert.
In FakeString2
, Ihr compareToIgnoreCase
hat ein implizites FakeString
Argument (this) und ein String-Argument, also kann es wiederum nicht an Stelle von Comparator<String>
stehen.
Dies ist der Unterschied zwischen einer Methodenreferenz für ein Objekt und einer Methodenreferenz für das Objekt , das verarbeitet wird .
Zuerst die Oracle-Beispiele
Sehen wir uns diesen ersten Fall an:
%Vor% Hier wird die Methode compareByName
an der übergebenen Instanz von myComparisonProvider
mit jedem Argumentpaar im sort
Algorithmus aufgerufen.
Also, wenn wir a
und b
vergleichen, rufen wir tatsächlich auf:
Nun, im zweiten Fall:
%Vor% Sie sortieren ein String[]
, so dass die Methode compareToIgnoreCase
für die Instanz String
aufgerufen wird, die gerade mit dem anderen String
als Argument sortiert wird.
Also, wenn wir a
und b
vergleichen, rufen wir tatsächlich:
Das sind also zwei verschiedene Fälle:
Auf Ihre Beispiele
Nun haben Sie in Ihrem ersten Beispiel auch String[]
und Sie versuchen es zu sortieren. Also:
Also, wenn wir a
und b
vergleichen, rufen wir tatsächlich:
Der einzige Unterschied ist compare
ist static
.
Nun ist die String[]
keine FakeString[]
, daher können wir diese Methode nicht für String
aufrufen. Deshalb müssen wir eine static
-Methode für FakeString
aufrufen. Aber wir können das auch nicht, weil wir eine Methode (String, String) -> int
benötigen, aber wir haben nur (String) -> int
- Kompilierungsfehler.
Im zweiten Beispiel ist das Problem genau dasselbe, da Sie immer noch String[]
haben. Und compareToIgnoreCase
hat die falsche Signatur.
Der Punkt, den Sie verpassen, ist der im Beispiel String::compareToIgnoreCase
; Die Methode wird an der String
aufgerufen, die gerade verarbeitet wird .