_ (podkreślenie) jest zastrzeżonym słowem kluczowym

94

Właśnie zastąpiłem sw poniższym wyrażeniu lambda przez _:

s -> Integer.parseInt(s)

Kompilator Eclipse mówi:

„_” nie powinno być używane jako identyfikator, ponieważ jest to zastrzeżone słowo kluczowe od poziomu źródła od 1.8.

Nie znalazłem żadnego wyjaśnienia w JLS §3.9 Struktura leksykalna / Słowa kluczowe.

Aubin
źródło

Odpowiedzi:

86

Miejsce, w którym należy szukać, to JLS §15.27.1. Parametry lambda

Jest to błąd czasu kompilacji, jeśli parametr lambda ma nazwę _ (czyli pojedynczy znak podkreślenia).

Odradza się używanie nazwy zmiennej _ w jakimkolwiek kontekście. Przyszłe wersje języka programowania Java mogą zastrzec tę nazwę jako słowo kluczowe i / lub nadać jej specjalną semantykę.

Zatem komunikat Eclipse wprowadza w błąd, zwłaszcza że ten sam komunikat jest używany w obu przypadkach, gdy generowany jest błąd dla parametru lambda lub gdy generowane jest ostrzeżenie dla dowolnego innego _identyfikatora.

Holger
źródło
24
Zauważ, że od wersji Java 9, _nie będzie dozwolone jako jakiekolwiek legalne nazwy identyfikatorów, a nie tylko jako nazwa parametru lambda. Naprawiono to w kompilacji 43: bugs.openjdk.java.net/browse/JDK-8061549
Jean-François Savard
3
@lscoughlin: Czy stwierdzenie „Przyszłe wersje języka programowania Java mogą zastrzec tę nazwę jako słowo kluczowe i / lub nadać jej specjalną semantykę” nie wystarczy? Cóż, zamień „może zarezerwować” na „użyje”, a otrzymasz obraz. Może ta wiadomość e-mail pomoże…
Holger
6
Co to jest? Java łamie wsteczną kompatybilność?
Arturo Torres Sánchez
8
@Arturo Torres Sánchez: to nic nowego. Były chwile, kiedy enumi assertbyły to identyfikatory prawne…
Holger
11
@Holger faktycznie istnieje mnóstwo języków, które używają podkreślenia jako symbolu zastępczego (Scala, Clojure, F #, SML, Erlang, żeby wymienić tylko kilka). To ustalony wzorzec, którego korzenie sięgają lat 90. lub 80., jak sądzę, więc nieposłuszeństwo jest dziwne.
om-nom-nom
25

Jest to faza 2 JEP 302 , która doda podkreślenie jako znak specjalny oznaczający nieużywane parametry w wyrażeniach lambda.

Traktowanie podkreśleń

W wielu językach często używa się znaku podkreślenia ( _) do oznaczenia nienazwanego parametru lambda (i podobnie dla parametrów metody i wyjątku):

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

Umożliwia to silniejsze statyczne sprawdzanie nieużywanych argumentów, a także umożliwia oznaczanie wielu argumentów jako nieużywanych. Jednakże, ponieważ podkreślenie było poprawnym identyfikatorem w Javie 8, kompatybilność wymagała od nas obrania bardziej pośredniej ścieżki do miejsca, w którym podkreślenie mogłoby pełnić tę rolę w Javie. Faza 1 zabraniała podkreślenia jako formalnej nazwy parametru lambda w Javie 8 (nie miało to konsekwencji dla zgodności, ponieważ lambdy wcześniej nie istniały) i wydano ostrzeżenie o używaniu podkreślenia jako identyfikatora w innych miejscach. Faza 2 pojawiła się w Javie 9, kiedy to ostrzeżenie stało się błędem. Możemy teraz zakończyć planowaną naprawę podkreślenia, aby wskazać nieużywaną lambdę, metodę lub parametr formalny catch.

Alexandre de Champeaux
źródło
2
To zastosowanie zostało omówione przez Briana Goetza w jego wykładzie Devoxx z 2017-11 na temat Projektu Amber .
Basil Bourque
OK, ale jaka jest alternatywa dla oznaczenia nieużywanych parametrów w J8? Czy to w ogóle niemożliwe?
Manuel
1
Obecnie używamy $do tego celu.
awenturin
1
Jestem teraz na Javie 14 i nadal nie mogę użyć podkreślenia jako nienazwanego parametru lambda. Wydaje się, że niezależnie od tego, co JCP zamierzał osiągnąć, osiągnęli coś przeciwnego.
Frans
1
@Frans Zauważ, że JEP jest (na dzień dzisiejszy) tylko na etapie kandydata. To nie zostało jeszcze zakończone. Więcej informacji na temat procesu JEP można znaleźć w JEP 1
Alexandre de Champeaux,