_ (Unterstrich) ist ein reserviertes Schlüsselwort

92

Ich habe gerade sim folgenden Lambda-Ausdruck ersetzt durch _:

s -> Integer.parseInt(s)

Der Eclipse-Compiler sagt:

'_' sollte nicht als Bezeichner verwendet werden, da es sich ab Quellstufe 1.8 um ein reserviertes Schlüsselwort handelt.

Ich habe keine Erklärung in JLS §3.9 Lexikalische Struktur / Schlüsselwörter gefunden.

Aubin
quelle

Antworten:

83

Der Ort zu suchen ist JLS §15.27.1. Lambda-Parameter

Es ist ein Fehler zur Kompilierungszeit, wenn ein Lambda-Parameter den Namen _ hat (dh ein einzelnes Unterstrichzeichen).

Von der Verwendung des Variablennamens _ in einem beliebigen Kontext wird abgeraten. Zukünftige Versionen der Programmiersprache Java können diesen Namen als Schlüsselwort reservieren und / oder ihm eine spezielle Semantik geben.

Die Eclipse-Nachricht ist daher irreführend, insbesondere da in beiden Fällen dieselbe Nachricht verwendet wird, wenn für einen Lambda-Parameter ein Fehler generiert wird oder wenn für einen anderen _Bezeichner eine Warnung generiert wird.

Holger
quelle
21
Beachten Sie, dass ab Java 9 _keine legalen Bezeichnernamen mehr zulässig sind und nicht nur ein Lambda-Parametername. Dies wurde tatsächlich in Build 43 behoben
Jean-François Savard
3
@lscoughlin: Ist die Aussage "Zukünftige Versionen der Java-Programmiersprache können diesen Namen möglicherweise als Schlüsselwort reservieren und / oder ihm eine spezielle Semantik geben" nicht ausreichend? Ersetzen Sie "kann reservieren" durch "wird verwenden", und Sie erhalten das Bild. Vielleicht hilft diese Mail-Referenz ...
Holger
5
Was ist das? Java bricht die Abwärtskompatibilität?
Arturo Torres Sánchez
8
@ Arturo Torres Sánchez: Das ist nichts Neues. Es gab Zeiten, in denen enumund assertwaren rechtliche Identifikatoren…
Holger
11
@Holger Tatsächlich gibt es Unmengen von Sprachen, die Unterstriche als Platzhalter für Namen verwenden (Scala, Clojure, F #, SML, Erlang, um nur einige zu nennen). Ich glaube, es ist ein etabliertes Muster, das bis in die 90er oder 80er Jahre zurückreicht. Es ist also seltsam, wenn man es nicht befolgt.
Om-Nom-Nom
22

Es ist die Phase 2 von JEP 302 , die einen Unterstrich als Sonderzeichen hinzufügt, um nicht verwendete Parameter in Lambda-Ausdrücken zu kennzeichnen.

Behandlung von Unterstrichen

In vielen Sprachen ist es üblich, einen Unterstrich ( _) zu verwenden, um einen unbenannten Lambda-Parameter zu bezeichnen (und ähnlich für Methoden- und Ausnahmeparameter):

BiFunction<Integer, String, String> biss = (i, _) -> String.valueOf(i);

Dies ermöglicht eine stärkere statische Überprüfung nicht verwendeter Argumente und die Kennzeichnung mehrerer Argumente als nicht verwendet. Da der Unterstrich ab Java 8 ein gültiger Bezeichner war, mussten wir aufgrund der Kompatibilität einen indirekteren Weg einschlagen, um dahin zu gelangen, wo der Unterstrich diese Rolle in Java übernehmen könnte. In Phase 1 wurde der Unterstrich als formaler Lambda-Parametername in Java 8 verboten (dies hatte keine Kompatibilitätsfolgen, da Lambdas zuvor nicht vorhanden waren), und es wurde eine Warnung ausgegeben, um den Unterstrich als Bezeichner an anderen Stellen zu verwenden. Phase 2 kam in Java 9, als diese Warnung zu einem Fehler wurde. Es steht uns nun frei, die geplante Rehabilitation des Unterstrichs abzuschließen, um einen nicht verwendeten Lambda, eine Methode oder einen formalen Fangparameter anzuzeigen.

Alexandre de Champeaux
quelle
1
Diese Verwendung wird von Brian Goetz in seinem Devoxx-Vortrag von 2017-11 über Project Amber erörtert .
Basil Bourque
OK, aber was ist die Alternative, um nicht verwendete Parameter in J8 zu kennzeichnen? Ist das überhaupt nicht möglich?
Manuel
1
Wir verwenden derzeit $für diesen Zweck.
Aventurin
Ich bin jetzt auf Java 14 und kann immer noch keinen Unterstrich als unbenannten Lambda-Parameter verwenden. Was auch immer die JCP erreichen wollte, es scheint, dass sie das Gegenteil erreicht haben.
Frans
@Frans Beachten Sie, dass sich der JEP (ab heute) nur in der Kandidatenphase befindet. Es wurde noch nicht abgeschlossen. Weitere Einzelheiten zum JEP-Prozess finden Sie unter JEP 1
Alexandre de Champeaux,