openjdk.ruOpenJDK на русском

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.