Lambda表达式 简介 语法 示例

Lambda 表达式也称为闭包,是匿名类的简短形式。Lambda 表达式简化了【单一抽象方法声明接口】的使用,因此 lambda 表达式也称为功能接口。
在 Java SE 7 中,单一方法接口可使用下列选项之一实现。
  • 创建接口实现类。
  • 创建匿名类。

可以使用 lambda 表达式实现功能接口,无需创建类或匿名类。Lambda 表达式只能用于单一方法声明接口。

Lambda 表达式旨在支持多核处理器架构,这种架构依赖于提供并行机制的软件,而该机制可以提高性能、减少完成时间。

Lambda 表达式具有以下优点:

  • 简明的语法
  • 方法引用和构造函数引用
  • 相比于匿名类,减少了运行时开销

Lambda 表达式的语法

Lambda 表达式的语法如下所示。

(formal parameter list) ->{ expression or statements }

参数列表是一个逗号分隔的形式参数列表,这些参数与功能接口中单一方法的形式参数相对应。指定参数类型是可选项;如果未指定参数类型,将从上下文推断。

参数列表必须用括号括起来,但当指定的单一参数不带参数类型时除外,指定单一形式参数时可以不带括号。如果功能接口方法不指定任何形式参数,则必须指定空括号。

参数列表后面是 -> 运算符,然后是 lambda 主体,即单一表达式或语句块。Lambda 主体的结果必须是下列值之一:

  • void,如果功能接口方法的结果是 void
  • Java 类型、基元类型或引用类型,与功能接口方法的返回类型相同

Lambda 主体根据以下选项之一返回结果:

  • 如果 lambda 主体是单一表达式,则返回表达式的值。
  • 如果该方法具有返回类型,且 lambda 主体不是单一表达式,则 lambda 主体必须使用 return 语句返回值。
  • 如果功能接口方法的结果是 void,可以提供一个 return 语句,但这不是必需的。

语句块必须包含在大括号内,除非语句块是一个方法调用语句,而其调用的方法的结果是 void。Lambda 主体的结果必须与功能接口中单一方法的结果相同。

例如,如果功能接口方法的结果是 void,则 lambda 表达式主体不能返回值。如果功能接口方法具有返回类型String,则 lambda 表达式主体必须返回 String。如果 lambda 主体是一条语句,并且该方法具有一个返回类型,则该语句必须是return 语句。调用 lambda 表达式时,将运行 lambda 主体中的代码。

功能接口

Lambda 表达式与功能接口一起使用,功能接口实际上是一种只有一个抽象方法的接口;功能接口可以包含一个同时也存在于 Object 类中的方法。功能接口的示例有 java.util.concurrent.Callable(具有单一方法 call())和 java.lang.Runnable(具有单一方法run())。

区别在于,匿名接口类需要指定一个实例创建表达式,以便接口和编译器用来创建接口实现类的实例。与指定接口类型(或类类型)的匿名类不同,lambda 表达式不指定接口类型。从上下文推断为其调用 lambda 表达式的功能接口,也称为 lambda 表达式的目标类型。

Lambda 表达式的目标类型

Lambda 表达式有一个隐式的目标类型与之关联,因为未明确指定接口类型。在 lambda 表达式中,lambda 转换的目标类型必须是一个功能接口。从上下文推断目标类型。因此,lambda 表达式只能用在可以推断目标类型的上下文中。此类上下文包括

  • 变量声明
  • 赋值
  • return 语句
  • 数组初始值设定项
  • 方法或构造函数的参数
  • Lambda 表达式主体
  • 三元条件表达式
  • 转换表达式

在 Eclipse IDE 中使用 Lambda 表达式

前提条件
  • 1、安装了 JDK 8 的 JRE
  • 2、所使用的 Eclipse 要支持 Java8 的编译
在 Eclipse 中,选择 Windows > Preferences > Java > Installed JREs,勾选JDK 8 的 JRE
Lambda表达式 简介 语法 示例
选择 Windows > Preferences > Java >Compiler,然后将 Compiler compliance level 设为 1.8。如果没有1.8的选项,说明此eclipse版本不支持。
Lambda表达式 简介 语法 示例
单击 Apply,然后单击 OK。
Lambda表达式 简介 语法 示例
Eclipse Luna  SR2已经添加了对Java8的支持,可直接到官网下载

在 AndroidStudio 中使用 Lambda 表达式

Gradle(Project)中添加classpath【classpath 'me.tatarka:gradle-retrolambda:3.2.0'】
Lambda表达式 简介 语法 示例
Gradle(Module)中添加apply【apply plugin: 'me.tatarka.retrolambda'】
Lambda表达式 简介 语法 示例
Gradle(Module)中添加compileOptions
  1. compileOptions {
  2. targetCompatibility 1.8
  3. sourceCompatibility 1.8
  4. }
Lambda表达式 简介 语法 示例
JDK版本选择1.8
Lambda表达式 简介 语法 示例

用 Lambda 表达式创建 Hello 应用程序

我们都很熟悉 Hello 应用程序,当我们提供一个姓名时,它会输出一条消息。Hello 类声明了两个字段、两个构造函数和一个 hello()方法来输出消息,如下所示。

  1. public class Hello {
  2. String firstname;
  3. String lastname;
  4. public Hello() {
  5. }
  6. public Hello(String firstname, String lastname) {
  7. this.firstname = firstname;
  8. this.lastname = lastname;
  9. }
  10. public void hello() {
  11. System.out.println("Hello " + firstname + " " + lastname);
  12. }
  13. public static void main(String[] args) {
  14. Hello hello = new Hello(args[0], args[1]);
  15. hello.hello();
  16. }
  17. }
现在,我们来看看 lambda 表达式如何简化 Hello 示例中的语法。
首先,我们需要创建一个功能接口,该接口包含一个返回“Hello”消息的方法。
  1. interface HelloService {
  2. String hello(String firstname, String lastname);
  3. }
创建一个 lambda 表达式,它包含两个参数,与接口方法的参数相匹配。在 lambda 表达式的主体中,使用 return 语句创建并返回根据firstname 和 lastname 构造的“Hello”消息。返回值的类型必须与接口方法的返回类型相同,并且 lambda 表达式的目标必须是功能接口HelloService。
  1. public class Test {
  2. public static void main(String[] args) {
  3. HelloService helloService = (String firstname, String lastname) -> {
  4. return "Hello " + firstname + " " + lastname;
  5. };
  6. System.out.println(helloService.hello("包青天", "白乾涛"));
  7. }
  8. }

Lambda 表达式中的局部变量

  • Lambda 表达式不会定义新的作用域,lambda 表达式的作用域与封闭作用域相同。如果 Lambda 主体声明的局部变量与封闭作用域内的变量重名,将产生编译器错误 Lambda expression's local variable i cannot re-declare another local variable defined in an enclosing scope
  • 局部变量无论是在 lambda 表达式主体中声明,还是在封闭作用域中声明,使用之前都必须先初始化,否则将产生编译器错误 The local variable i may not have been initialized
  • lambda 表达式中使用的变量必须处于终态或等效终态,否则将产生编译器错误 Variable i is required to be final or effectively final
  • Lambda 主体中的 this 和 super 引用与封闭上下文中一样,因为 lambda 表达式不会引入新的作用域,这与匿名类不同。

Lambda 表达式是一种匿名方法

Lambda 表达式实际上是一种匿名方法实现;指定形式参数,并使用 return 语句返回值。匿名方法必须按照以下规则所规定的与其实现的功能接口方法兼容。

  • Lambda 表达式返回的结果必须与功能接口方法的结果兼容。返回值的类型可以是功能接口方法声明中返回类型的子类型。
  • Lambda 表达式签名必须与功能接口方法的签名相同。
  • Lambda 表达式只能抛出那些在功能接口方法的 throws 子句中声明了异常类型或异常超类型的异常。

Lambda 表达式是一种多态表达式

Lambda 表达式的类型是从目标类型推导出来的类型。相同的 lambda 表达式在不同的上下文中可以有不同的类型。此类表达式称为多态表达式。

不支持泛型 Lambda。Lambda 表达式不能引入类型变量。

上一篇:编写一致的符合习惯的javascript


下一篇:Envoy 代替nginx https://www.jianshu.com/p/0a1f67b42fdb