跳到主要内容

JEP 323:Lambda 参数的局部变量语法

概括

允许var在声明隐式类型 lambda 表达式的形式参数时使用。

目标

  • 将隐式类型 lambda 表达式中的形式参数声明的语法与局部变量声明的语法对齐。

非目标

  • 将任何其他类型的变量声明(例如方法的形式参数)的语法与局部变量声明的语法对齐。

动机

lambda 表达式可以是_隐式类型的_,其中推断其所有形式参数的类型:

(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”作为隐式类型 lambda 表达式的形式参数:

(var x, var y) -> x.process(y)   // implicit typed lambda expression

一致性的好处之一是修饰符(尤其是注释)可以应用于局部变量和 lambda 形式而不失简洁:

@Nonnull var x = new Foo();
(@Nonnull var x, @Nullable var y) -> x.process(y)

描述

var对于隐式类型 lambda 表达式的形式参数,允许使用保留的类型名称,以便:

(var x, var y) -> x.process(y)

相当于:

(x, y) -> x.process(y)

隐式类型 lambda 表达式必须用于var其所有形式参数,或者不用于任何形式参数。此外,var仅允许隐式类型 lambda 表达式的形式参数 --- 显式类型 lambda 表达式继续为其_所有_形式参数指定明显类型,因此不允许某些形式参数具有明显类型,而其他形式参数则使用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

理论上,可以有一个类似于上面最后一行的 lambda 表达式,它是半显式类型的(或半隐式类型的,取决于您的观点)。但是,它超出了本 JEP 的范围,因为它严重影响类型推断和重载解析。这是保留 lambda 表达式必须指定所有清单参数类型或不指定任何参数类型这一限制的主要原因。我们还希望强制隐式类型 lambda 表达式的参数推断类型无论是否var使用都是相同的。我们可能会在未来的 JEP 中回到部分推理的问题。另外,我们不希望损害简写语法的简洁性,因此我们不允许使用如下表达式:

var x -> x.foo()

备择方案

继续像 Java SE 8 中一样声明隐式类型的 lambda 表达式。

风险和假设

var当在隐式类型 lambda 表达式中的参数名称之前添加时,此 JEP 不存在源不兼容的风险,因为为没有 的参数推断的类型var与使用 推断的类型相同var