JEP 323: Local-Variable Syntax for Lambda Parameters | Lambda 参数的局部变量语法
摘要
允许在声明隐式类型 lambda 表达式的形式参数时使用 var
。
目标
- 使隐式类型 lambda 表达式中形式参数的声明语法与局部变量声明的语法保持一致。
非目标
- 使任何其他类型的变量声明(例如方法的形式参数)的语法与局部变量声明的语法保持一致。
动机
Lambda 表达式 可能是 隐式类型 的,即所有形式参数的类型都是推断出来的:
java
(x, y) -> x.process(y) // 隐式类型 lambda 表达式
Java SE 10 使局部变量支持隐式类型:
java
var x = new Foo();
for (var x : xs) { ... }
try (var x = ...) { ... } catch ...
为了与局部变量保持一致,我们希望在隐式类型 lambda 表达式的形式参数中使用 var
:
java
(var x, var y) -> x.process(y) // 隐式类型 lambda 表达式
统一性的一个好处是,修饰符(特别是注解)可以应用于局部变量和 lambda 形式参数,同时不失去简洁性:
java
@Nonnull var x = new Foo();
(@Nonnull var x, @Nullable var y) -> x.process(y)
描述
对于隐式类型 lambda 表达式的形式参数,允许使用保留类型名称 var
,使得:
java
(var x, var y) -> x.process(y)
等价于:
java
(x, y) -> x.process(y)
隐式类型 lambda 表达式必须对所有形式参数都使用 var
,或者一个都不用。此外,var
仅允许用于隐式类型 lambda 表达式的形式参数——显式类型 lambda 表达式继续为所有形式参数指定明确类型,因此不允许一些形式参数有明确类型而其他使用 var
。以下示例是非法的:
java
(var x, y) -> x.process(y) // 隐式类型 lambda 表达式中不能混用 'var' 和 '无 var'
(var x, int y) -> x.process(y) // 显式类型 lambda 表达式中不能混用 'var' 和 明确类型
从理论上讲,可以有像上面最后一行那样的 lambda 表达式,它是半显式类型(或半隐式类型,取决于你的观点)。但是,这超出了本 JEP 的范围,因为它深刻影响了类型推断和重载解析。这是保持 lambda 表达式必须指定所有明确参数类型或都不指定的限制的主要原因。我们还希望确保隐式类型 lambda 表达式的参数推断出的类型,在使用 var
或不使用时保持一致。我们可能会在将来的 JEP 中回到部分推断的问题。此外,我们不想损害简写语法的简洁性,因此不允许类似以下表达式:
java
var x -> x.foo()
替代方案
继续像 Java SE 8 那样声明隐式类型 lambda 表达式。
风险与假设
在隐式类型 lambda 表达式中的参数名前添加 var
时,这个 JEP 不会产生源代码不兼容的风险,因为不带 var
的参数推断出的类型与带 var
的参数推断出的类型相同。