JEP 323: Local-Variable Syntax for Lambda Parameters
Синтаксис объявления локальных переменных для параметров лямбда-выражений
| Автор | Brian Goetz |
| Ответственный | Vicente Arturo Romero Zaldivar |
| Тип | Feature |
| Область | SE |
| Статус | Closed / Delivered |
| Выпуск | 11 |
| Компонент | specification / language |
| Обсуждение | amber dash dev at openjdk dot java dot net |
| Трудоёмкость | XS |
| Длительность | XS |
| Связан с | JEP 286: Local-Variable Type Inference |
| Рецензенты | Alex Buckley |
| Создан | 2017/12/08 15:15 |
| Обновлён | 2026/01/09 21:33 |
| Задача | 8193259 |
Аннотация
Разрешить использовать var при объявлении формальных параметров лямбда-выражений с неявной типизацией.
Цели
- Привести синтаксис объявления формального параметра в лямбда-выражении с неявной типизацией в соответствие с синтаксисом объявления локальной переменной.
Что не является целью
- Привести синтаксис объявлений переменных любого другого вида, например формального параметра метода, в соответствие с синтаксисом объявления локальной переменной.
Мотивация
Лямбда-выражение может иметь неявную типизацию, при которой типы всех его формальных параметров выводятся автоматически:
(x, y) -> x.process(y) // implicitly typed lambda expression
В Java SE 10 неявная типизация стала доступна для локальных переменных:
var x = new Foo();
for (var x : xs) { ... }
try (var x = ...) { ... } catch ...
Для единообразия с локальными переменными мы хотим разрешить «var» для формальных параметров лямбда-выражения с неявной типизацией:
(var x, var y) -> x.process(y) // implicit typed lambda expression
Одно из преимуществ единообразия в том, что модификаторы, в частности аннотации, можно применять к локальным переменным и формальным параметрам лямбда-выражений, не теряя краткости:
@Nonnull var x = new Foo();
(@Nonnull var x, @Nullable var y) -> x.process(y)
Описание
Для формальных параметров лямбда-выражений с неявной типизацией разрешить использовать зарезервированное имя типа var, так чтобы запись:
(var x, var y) -> x.process(y)
была эквивалентна записи:
(x, y) -> x.process(y)
Лямбда-выражение с неявной типизацией должно использовать var либо для всех своих формальных параметров, либо ни для одного из них. Кроме того, var разрешён только для формальных параметров лямбда-выражений с неявной типизацией — в лямбда-выражениях с явной типизацией по-прежнему указываются явные типы для всех формальных параметров, поэтому не допускается, чтобы одни формальные параметры имели явные типы, а другие использовали var. Следующие примеры недопустимы:
(var x, y) -> x.process(y) // Cannot mix 'var' and 'no var' in implicitly typed lambda expression
(var x, int y) -> x.process(y) // Cannot mix 'var' and manifest types in explicitly typed lambda expression
Теоретически возможно лямбда-выражение, подобное последней строке выше, с полуявной типизацией (или полунеявной, в зависимости от точки зрения). Однако это выходит за рамки данного JEP, поскольку глубоко затрагивает вывод типов и разрешение перегрузки. Это основная причина сохранить ограничение, по которому лямбда-выражение должно указывать либо все явные типы параметров, либо ни одного. Мы также хотим гарантировать, что тип, выведенный для параметра лямбда-выражения с неявной типизацией, один и тот же независимо от того, используется var или нет. Возможно, мы вернёмся к проблеме частичного вывода типов в одном из будущих JEP. Кроме того, мы не хотим жертвовать краткостью сокращённого синтаксиса, поэтому не разрешим выражения вида:
var x -> x.foo()
Альтернативы
Продолжать объявлять лямбда-выражения с неявной типизацией так же, как в Java SE 8.
Риски и допущения
У этого JEP нет риска несовместимости на уровне исходного кода при добавлении var перед именем параметра в лямбда-выражении с неявной типизацией, поскольку тип, выведенный для параметра без var, совпадает с типом, выведенным с var.