Java 8 预计将在 2013 年发布,Java 8 将支持 Lambda 功能,尽管该规范还在不断的变化,但是 Java 8 的开发版已经实现了对 lambda 的支持。
关于 lambda 表达式的定义请看维基百科。
该文章将带你熟悉 lambda 语法,以及使用集合 API 中的 lambda 以及相关的语言增强,本文所有的代码都是在 JDK 8 lambda build b39 编译。
只包含一个方法的接口被称为功能接口,Lambda 表达式用用于任何功能接口适用的地方。
java.awt.event.ActionListener 就是一个功能接口,因为它只有一个方法:void actionPerformed(ActionEvent). 在 Java 7 中我们会编写如下代码:
编译器知道lambda 表达式必须符合 void actionPerformed(ActionEvent) 方法的定义。看起来 lambda 实体返回 void,实际上它可以推断出参数 e 的类型是 java.awt.event.ActionEvent.
Java 8 的类库包含一个新的包 java.util.functions ,这个包中有很多新的功能接口,这些接口可与集合 API 一起使用。
使用谓词 (Predicate) 来筛选集合:
我们可使用一个新的迭代器方法来替换 for 循环 void forEach(Block< super T>):
最后的结果就是用更少的代码来处理集合:
我们可通过 :: 语法来引用某个方法。方法引用被认为是跟 lambda 表达式一样的,可用于功能接口所适用的地方。
最后,我们创建一个引用到随意实例的例子:
这里我们无需绑定方法引用到某个实例,我们直接将实例做为功能接口的参数进行传递。
直到今天的 Java ,都不可能为一个接口添加方法而不会影响到已有的实现类。而 Java 8 允许你为接口自身指定一个默认的实现:
lambda 不只是可以减少很多代码的编写,其字节码和运行时的实现也比 Java 7 中的匿名类的效率更高。针对每一个 lambda 表达式,编译器都会创建一个对应的形如 lambda$1() 这样的方法。这个过程被称之为 lambda body desugaring. 当遇见一个 lambda 表达式,编译器将会发起一个 invokedynamic 调用,并从目标功能接口中获取返回值。
本文很多内容都基于 Brian Goetz 的文章:State of the Lambda, State of the Lambda: Libraries Edition and Translation of Lambda Expressions. 这些文字详细描述了 lambda 语法、变量捕获、类型接口和编译等内容。