Java 8 und Methodenreferenzen - speziell compareToIgnoreCase

8

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.

%Vor%

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     
Rich 19.04.2015, 20:00
quelle

2 Antworten

6

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.

    
Eran 19.04.2015, 20:06
quelle
5

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:

%Vor%

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:

%Vor%

Das sind also zwei verschiedene Fälle:

  • eine, in der Sie eine Methode für eine beliebige Objektinstanz übergeben; und
  • eine, in der Sie eine Methode übergeben, die für die gerade verarbeitete Instanz aufgerufen wird.

Auf Ihre Beispiele

Nun haben Sie in Ihrem ersten Beispiel auch String[] und Sie versuchen es zu sortieren. Also:

%Vor%

Also, wenn wir a und b vergleichen, rufen wir tatsächlich:

%Vor%

Der einzige Unterschied ist compare ist static .

%Vor%

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.

TL; DR:

Der Punkt, den Sie verpassen, ist der im Beispiel String::compareToIgnoreCase ; Die Methode wird an der String aufgerufen, die gerade verarbeitet wird .

    
Boris the Spider 19.04.2015 20:07
quelle

Tags und Links