java11新特性--Local-Variable Syntax for Lambda Parameters

1,044 阅读2分钟

简介

允许在隐式类型的lambda表达式中使用var来声明参数

目标

统一隐式类型lambda表达式参数声明语法和普通本地变量声明语法

动机

一个lambda表达式可能是隐式类型的,它的类型是靠推断获得的,如下:

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

在java 10中出现了隐式类型的本地变量:

var x = new Foo();
for (var x : xs) { ... }
try (var x = ...) { ... } catch ...

为了统一本地变量,我们希望能够在隐式的lambda表达式中使用var声明参数:

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

这种统一的一个好处就是modifiers(特别是一些注解)可以完全一致的用于本地变量和lambda表达式:

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

描述

对于隐式类型的lambda表达式,允许省略掉var,如下:

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

和下面是等价的

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

隐含类型的lambda表达式的参数要么全部使用var,要么全不使用var。并且var只能用于隐含类型的lambda表达式,那些显示类型的lambda表达式是不能用var的,比如下面的例子是不合法的:

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

理论上说上面的第二种半隐式类型(也有人叫半显示类型),但是它已经超出本JEP的讨论范围了,因为它影响到推断和重载机制。这就是为什么当前强制限制lambda表达式只能是全显示或隐式的原因。我们也强制无论隐式lambda表达式的参数是否带var都不影响推断。我们可能在未来的JEP中解决部分推断的问题,但是我们不希望你以如下速记方式的语法,所以下面的表达式是不合法的:

var x -> x.foo()