Intellij - kann durch Methodenreferenz ersetzt werden

73

Immer wenn ich Lambda-Ausdrücke wie diesen verwende:

.map(obj -> foo.makeSomething(obj))

IntelliJ schlägt vor: "Kann durch Methodenreferenz ersetzt werden ...". Und wenn ich es dann versuche:

.map(Foo::makeSomething)

Ich erhalte die folgende Anweisung: "Nicht statische Methode kann nicht aus einem statischen Kontext referenziert werden".

Warum schlägt Idea vor, dass ich eine Methodenreferenz verwenden sollte, wenn diese nicht korrekt ist?

Nutzer
quelle
11
Schlägt es tatsächlich diesen Ersatz vor? Oder ist es genau das, was Sie selbst schreiben? Ich hätte erwartet foo::makeSomething, was funktionieren würde.
Andy Turner
4
Es ist foo::makeSomething. Sie möchten die Methode für das Objekt foo aufrufen, nicht für die Klasse Foo. Sie können IntelliJ auch einfach den Code für Sie transformieren lassen (Alt-Enter).
JB Nizet
Mögliches Duplikat der Java 8-Methode Verweis auf nicht statische Methode
Andrew Li
Welche Version von IntelliJ IDEA verwenden Sie?
Mike Nakis
@JBNizet TY für diese Abkürzung - Herrgott für mein Leben Ich konnte nicht herausfinden, wie ich IJ sagen soll, dass er es tun soll! Alles, was es gab, war ein nutzloses Popup, ein noch nutzloserer Vorschlag, zu Einstellungen zu gehen, in denen für diesen genauen Code nichts relevant war !! Jetzt immer mehr in Richtung Eclipse
lehnen

Antworten:

98

Während Sie schreiben:

map(Foo::makeSomething)

Der Compiler erwartet eine dieser beiden Möglichkeiten:

  • Aufrufen einer Foo.makeSomething()Instanzmethode für den ersten Parameter des Lambda, der als definiert werden muss Foo.

  • Aufrufen einer Foo.makeSomething()statischen Methode.

Die erste Möglichkeit wird vom Compiler ausgeschlossen, da der erste Parameter des deklarierten Lambda objnicht a ist Foo.

Und laut Ihrer Fehlermeldung Foo.makeSomething()ist eine Instanzmethode:

Nicht statische Methoden können nicht aus einem statischen Kontext referenziert werden. "

Die zweite Möglichkeit (Aufrufen einer Foo.makeSomething()statischen Methode) ist also ebenfalls nicht zulässig, da sie makeSomething()nicht statisch ist.


Sie möchten die makeSomething()Instanzmethode auf eine Variable anwenden , die nicht Teil der Lambda-Parameter ist.
Sie können dies tun, müssen jedoch eine andere Syntax verwenden.

Anstatt anzugeben Foo::, verwenden Sie foo::.
Auf diese Weise wird die Instanzmethode makeSomething()auf die fooVariable angewendet :

map(foo::makeSomething)

IntelliJ Intention

Beachten Sie, dass Inspektionen, die Lambdas melden, die durch Methodenreferenzen ersetzt werden können, von der IDE auch automatisch über eine Absicht überarbeitet werden können.
Setzen Sie dazu den Cursor auf das Lambda (irgendwo darauf) und zeigen Sie kontextbezogene Absichten an ( Alt+Enterstandardmäßig). Sie sollten die Absicht sehen:

Ersetzen Sie Lambda durch Methodenreferenz

Einige Screenshots:

Absichtsvorschlag

Absichtsergebnis

davidxxx
quelle
6
Vielen Dank, ich wusste nicht, dass ich Referenz mit Objekt verwenden kann. Ich denke, es funktioniert nur, wenn ich ClassName :: metohd aufrufe.
Benutzer
1
Gern geschehen :) Tatsächlich haben Sie drei Fälle, in denen Sie Methodenreferenzen anwenden können: 1) statische Methode, 2) Instanzmethode für Parameter des Lambda und 3) Instanzmethode für eine Variable, die nicht in den Lambda-Parametern deklariert ist. Und im letzten Fall ist die Syntax tatsächlich anders.
Davidxxx
Wie @Eli bereits sagte, müssen Sie 'this' anstelle des Klassennamens verwenden, wenn sich die Methode in derselben Klasse befindet.
CodeSlave