跳到主要内容

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

QWen Max 中英对照 JEP 323 Local-Variable Syntax for Lambda Parameters

概述

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

目标

  • 将隐式类型 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 ...

为了与局部变量保持一致,我们希望允许在隐式类型的 lambda 表达式的形参中使用 var

(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)

描述

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

(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()

替代方案

继续声明隐式类型的 lambda 表达式,如同在 Java SE 8 中一样。

风险与假设

当在隐式类型 lambda 表达式的参数名称前添加 var 时,此 JEP(Java Enhancement Proposal)不存在源不兼容的风险,因为无论是否使用 var,推断出的参数类型都是相同的。