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
选择 Windows > Preferences > Java >Compiler,然后将 Compiler compliance level 设为 1.8。如果没有1.8的选项,说明此eclipse版本不支持。

单击 Apply,然后单击 OK。

Eclipse Luna  SR2已经添加了对Java8的支持,可直接到官网下载

在 AndroidStudio 中使用 Lambda 表达式

Gradle(Project)中添加classpath【classpath 'me.tatarka:gradle-retrolambda:3.2.0'】

Gradle(Module)中添加apply【apply plugin: 'me.tatarka.retrolambda'】

Gradle(Module)中添加compileOptions
  1. compileOptions {
  2. targetCompatibility 1.8
  3. sourceCompatibility 1.8
  4. }

JDK版本选择1.8

用 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 表达式不能引入类型变量。

Lambda表达式 简介 语法 示例的更多相关文章

  1. Lambda表达式 简介 语法 示例 匿名内部类

    在AS中使用 Lambda 表达式 Demo地址:https://github.com/baiqiantao/MultiTypeTest.git Gradle(Project级别)中添加classpa ...

  2. Java 8特性探究(1):通往lambda之路与 lambda表达式10个示例

    本文由 ImportNew 函数式接口 函数式接口(functional interface 也叫功能性接口,其实是同一个东西).简单来说,函数式接口是只包含一个方法的接口.比如Java标准库中的ja ...

  3. Java 8 Lambda表达式10个示例【存】

    PS:不能完全参考文章的代码,请参考这个文件http://files.cnblogs.com/files/AIThink/Test01.zip 在Java 8之前,如果想将行为传入函数,仅有的选择就是 ...

  4. java8 快速入门 lambda表达式 Java8 lambda表达式10个示例

    本文由 ImportNew - lemeilleur 翻译自 javarevisited.欢迎加入翻译小组.转载请见文末要求. Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发 ...

  5. Java8 lambda表达式10个示例

    Java 8 刚于几周前发布,日期是2014年3月18日,这次开创性的发布在Java社区引发了不少讨论,并让大家感到激动.特性之一便是随同发布的lambda表达式,它将允许我们将行为传到函数里.在Ja ...

  6. Lambda表达式常用代码示例

    Lambda表达式常用代码示例 2017-10-24 目录 1 Lambda表达式是什么2 Lambda表达式语法3 函数式接口是什么  3.1 常用函数式接口4 Lambdas和Streams结合使 ...

  7. Java8的Lambda表达式简介

    先阐述一下JSR(Java Specification Requests)规范,即Java语言的规范提案.是向JCP(Java Community Process)提出新增一个标准化技术规范的正式请求 ...

  8. Java8 lambda表达式10个示例<转>

    例1.用lambda表达式实现Runnable 我开始使用Java 8时,首先做的就是使用lambda表达式替换匿名类,而实现Runnable接口是匿名类的最好示例.看一下Java 8之前的runna ...

  9. 【Java8新特性】Lambda表达式基础语法,都在这儿了!!

    写在前面 前面积极响应读者的需求,写了两篇Java新特性的文章.有小伙伴留言说:感觉Lambda表达式很强大啊!一行代码就能够搞定那么多功能!我想学习下Lambda表达式的语法,可以吗?我的回答是:没 ...

随机推荐

  1. WAMP集成环境更改web根目录

    使用WAMP集成环境,如何更改web根目录 做php开发使用WAMP集成环境的同学大部分有过这样的经历:如果你试图修改web根目录,那么你肯定会想到要修改apache/apache2.2.11/con ...

  2. codebook法分割前景目标

    利用codebook法训练得到背景模型后,对背景差分得到的掩模图像去噪声并找到较大连通域.相对于平均背景法,它的分割效果更好些.当然,分割效果和背景模型训练的帧数有很大关系,适当调整一些参数会得到更好 ...

  3. OBJC运行时方法替换(Method swizzling)

    在上周associated objects一文中,我们开始探索Objective-C运行时的一些黑魔法.本周我们继续前行,来讨论可能是最受争议的运行时技术:method swizzling.   Me ...

  4. 使用模版引擎填充重复dom元素

    引入arttemplate,定义newajax发送跨域请求获得数据,将获得的数据用定义的格式渲染 <!DOCTYPE html><html lang="en"&g ...

  5. temp 临时文件

    放假了,放假了:http://blog.csdn.net/skywalker_only/article/details/17076851 nucht2.2.1爆出如下异常: Exception in ...

  6. 【转】web开发需要知道的事情

    在StackExchange上有人问了这样一个问题:What should every programmer know about web development?(关于Web开发,什么是所有程序员需 ...

  7. BZOJ 3106 棋盘游戏

    Description 一个\(n \times n(n \le 2)\)棋盘上有黑白棋子各一枚.游戏者A和B轮流移动棋子,A先走. A的移动规则:只能移动白棋子.可以往上下左右四个方向之一移动一格. ...

  8. BZOJ 1050 旅行

    Description 给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000).给你两个顶点S和T,求一条路径,使得路径上最大 ...

  9. 【Java】Java Socket编程(1)基本的术语和概念

    计算机程序能够相互联网,相互通讯,这使一切都成为可能,这也是当今互联网存在的基础.那么程序是如何通过网络相互通信的呢?这就是我记录这系列的笔记的原因.Java语言从一开始就是为了互联网而设计的,它为实 ...

  10. 查看Redis信息和状态

    原文转自:http://redisdoc.com/server/info.html INFO [section] 以一种易于解释(parse)且易于阅读的格式,返回关于 Redis 服务器的各种信息和 ...