_ (подчеркивание) - зарезервированное ключевое слово

94

Я только что заменил sследующее лямбда-выражение на _:

s -> Integer.parseInt(s)

Компилятор Eclipse говорит:

'_' не следует использовать в качестве идентификатора, поскольку это зарезервированное ключевое слово начиная с уровня источника 1.8.

Я не нашел никаких объяснений в лексической структуре / ключевых словах JLS §3.9 .

Обен
источник

Ответы:

86

Место для поиска - JLS §15.27.1. Лямбда-параметры

Если лямбда-параметр имеет имя _ (то есть один символ подчеркивания), это ошибка времени компиляции.

Не рекомендуется использовать имя переменной _ в любом контексте. В будущих версиях языка программирования Java это имя может быть зарезервировано как ключевое слово и / или придать ему особую семантику.

Таким образом, сообщение Eclipse вводит в заблуждение, тем более что одно и то же сообщение используется в обоих случаях, когда генерируется ошибка для лямбда-параметра или когда генерируется предупреждение для любого другого _идентификатора.

Хольгер
источник
24
Обратите внимание, что начиная с Java 9, _будут запрещены любые допустимые имена идентификаторов, а не только имя лямбда-параметра. Фактически это было исправлено в сборке 43: bugs.openjdk.java.net/browse/JDK-8061549
Жан-Франсуа Савар,
3
@lscoughlin: Разве не достаточно утверждения «Будущие версии языка программирования Java могут зарезервировать это имя как ключевое слово и / или придать ему особую семантику»? Что ж, замените «может зарезервировать» на «будет использовать», и вы получите картину. Может быть, эта почтовая ссылка поможет…
Хольгер
6
Что это? Java нарушает обратную совместимость?
Артуро Торрес Санчес
8
@ Артуро Торрес Санчес: в этом нет ничего нового. Были времена, когда enumи assertбыли законными идентификаторами…
Хольгер
11
@Holger на самом деле существует множество языков, в которых подчеркивание используется в качестве заполнителя имени (Scala, Clojure, F #, SML, Erlang, и это лишь некоторые из них). Я считаю, что это устоявшаяся модель, которая восходит к 90-м или 80-м годам, поэтому непослушание ему - странно.
om-nom-nom
25

Это фаза 2 JEP 302 , которая добавит подчеркивание в качестве специального символа для обозначения неиспользуемых параметров в лямбда-выражениях.

Обработка подчеркивания

Во многих языках часто используется подчеркивание (_ ) для обозначения безымянного лямбда-параметра (и аналогично для параметров метода и исключения):

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

Это обеспечивает более строгую статическую проверку неиспользуемых аргументов, а также позволяет помечать несколько аргументов как неиспользуемые. Однако, поскольку подчеркивание было допустимым идентификатором начиная с Java 8, совместимость потребовала от нас выбора более косвенного пути, чтобы добраться до того места, где подчеркивание могло бы выполнять эту роль в Java. Фаза 1 запрещала подчеркивание как формальное имя параметра лямбда в Java 8 (это не имело последствий для совместимости, так как лямбда-выражения ранее не существовали), и было выдано предупреждение за использование подчеркивания в качестве идентификатора в других местах. Фаза 2 наступила в Java 9, когда это предупреждение превратилось в ошибку. Теперь мы можем завершить запланированное восстановление подчеркивания, чтобы указать неиспользуемые лямбда, метод или формальный параметр catch.

Александр де Шампо
источник
2
Это использование обсуждается Брайаном Гетцем в своем выступлении на Devoxx в 2017–2011 годах о Project Amber .
Basil Bourque
Хорошо, но какова альтернатива обозначению неиспользуемых параметров в J8? Это вообще невозможно?
Мануэль
1
В настоящее время мы используем $для этой цели.
авантюрин
1
Сейчас я использую Java 14, и я все еще не могу использовать подчеркивание в качестве безымянного лямбда-параметра. Независимо от того, чего намеревалась достичь JCP, похоже, они добились противоположного.
Франс
1
@Frans Обратите внимание, что JEP (на сегодняшний день) находится только в стадии кандидата. Он еще не завершен. Для получения дополнительной информации о процессе JEP см. JEP 1
Александр де Шампо,
5

Изменения языка Java для Java SE 9 https://docs.oracle.com/javase/9/language/toc.htm#JSLAN-GUID-16A5183A-DC0D-4A96-B9D8-AAC9671222DD

Начиная с Java 9, символ _ больше не может использоваться в качестве идентификатора, а не только в контексте лямбда.

Знак подчеркивания не является допустимым именем.

Если вы используете символ подчеркивания ("_") в качестве идентификатора, ваш исходный код больше не может быть скомпилирован.

Ангел Ко
источник