Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

目录

Lambda 表达式

Lambda 表达式也称为闭包,是匿名内部类的简短形式。

Lambda 表达式简化了单一方法声明接口的使用,因此 lambda 表达式也称为功能接口(只有一个抽象方法的接口)。

使用 lambda 表达式实现功能接口时,无需创建类或匿名类。

Lambda 表达式具有以下优点:

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

基本语法

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

参数列表

  • 参数列表是一个逗号分隔的形式参数列表,这些参数与功能接口中单一方法的形式参数相对应。
  • 参数列表中的参数类型是可选项,如果未指定参数类型,将从上下文推断。
  • 参数列表必须用小括号括起来,但如果只有一个参数且不带参数类型时小括号可以省略
  • 参数列表如果为空(即:功能接口方法没有形式参数),则必须指定空括号

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

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

语句块必须包含在大括号内,除非语句块是一个方法调用语句,且功能接口方法的返回结果是void。

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

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

Lambda 表达式中的局部变量

Lambda 表达式不会定义新的作用域,lambda 表达式的作用域与封闭作用域相同。

Lambda 主体中的 this 和 super 引用与封闭上下文中一样,因为 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 表达式

在AS中使用 Lambda 表达式

File -> Project Structure -> SDK location -> JDK location -> JDK版本选择1.8

android {
compileOptions {
targetCompatibility JavaVersion.VERSION_1_8
sourceCompatibility JavaVersion.VERSION_1_8
}
}

在Eclipse中使用 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的支持,可直接到官网下载

使用示例

没有参数

new Thread(() -> {
System.out.println("包青天");
}).start();

只有一行语句时,可以进一步简化为:

new Thread(() -> System.out.println("包青天")).start();
new Thread(() -> runOnUiThread(() -> System.out.println("包青天"))).start();

但是如果有多行语句,就没法简化了

单一参数

imageView.setOnClickListener(v -> {
Toast.makeText(this, "包青天", Toast.LENGTH_SHORT).show();
});

同样,只有一行语句时,可以进一步简化为:

imageView.setOnClickListener((View v) -> System.out.println("包青天")); //带类型
imageView.setOnClickListener((v) -> System.out.println("包青天")); //带小括号
imageView.setOnClickListener(v -> System.out.println("包青天")); //省略小括号
imageView.setOnClickListener(v -> System.out.println(v));

如果只有一行方法引用的语句,且此方法没有返回值,且此方法仅有一个参数,且此方法的此参数就是 Lambda 表达式中参数列表中的那个参数,可以进一步简化为方法引用(method reference)

imageView.setOnClickListener(v -> test(v));

imageView.setOnClickListener(this::test); //普通方法
imageView.setOnClickListener(System.out::println); //静态方法
imageView.setOnClickListener(SplashActivity::test); //静态方法

多个参数

listView.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id) -> {
Toast.makeText(this, "position=" + position, Toast.LENGTH_SHORT).show();
});

同样,只有一行语句时,可以进一步简化为:

listView.setOnItemClickListener((AdapterView<?> parent, View view, int position, long id) -> System.out.println(position));
listView.setOnItemClickListener((parent, view, position, id) -> System.out.println(position));

使用局限性

1、只适用于单一方法的接口,如果接口有多个需要实现的方法,则不能使用,如:

listView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
} @Override
public void onScroll(AbsListView view, int first, int count, int total) {
}
});

这是 Lambda 表达式最大的局限性

2、如果需要在匿名内部类中定义成员变量,则不能使用,如:

listView.setOnClickListener(new View.OnClickListener() {
private boolean b; @Override
public void onClick(View v) {
}
});

其实这里的成员变量没有任何意义,和定义成局部变量没什么区别

3、如果需要在匿名内部类中使用到匿名内部类的this、super,而非如外部类的this、super,则不能使用,如:

view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
//这里的this代表的是匿名内部类OnGlobalLayoutListener
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);//使用到了this
}
});

Lambda 主体中的 this、super 引用与封闭上下文中一样,因为 lambda 表达式不会引入新的作用域,这与匿名类不同。

Lambda 表达式中使用的this、super是指外部类,其实往往这是 Lambda 的优点而非缺点,因为我们往往需要的就是外部类的this、super

2017-07-17

Lambda表达式 简介 语法 示例 匿名内部类的更多相关文章

  1. Lambda表达式 简介 语法 示例

    Lambda 表达式也称为闭包,是匿名类的简短形式.Lambda 表达式简化了[单一抽象方法声明接口]的使用,因此 lambda 表达式也称为功能接口. 在 Java SE 7 中,单一方法接口可使用 ...

  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表达式10个示例<转>

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

  8. java8:(Lambda 表达式简介)

    JDK8的新特性——Lambda表达式 JDK8已经发布快4年的时间了,现在来谈它的新特性显得略微的有点“不合时宜”.尽管JDK8已不再“新”,但它的重要特性之一——Lambda表达式依然是不被大部分 ...

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

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

随机推荐

  1. win10 远程桌面远程电脑时每次要输入密码及身份验证错误,要求的函数不受支持问题解决

    解决以前每次远程时能能记住密码,更新系统补丁后现在每次登录要输入密码了及远程时提示身份验证错误,要求的函数不受支持问题 解决方法一.卸载更新安装的新补丁,远程桌面正常,能记住密码 解决方法二.修改注册 ...

  2. 使用UniBeast安装Hackintosh(黑苹果)

    前期准备 UniBeast 原版macOS Sierra安装包,由于苹果并没有提供完整dmg的下载地址,我也不在此提供,大家可以从信任的途径取得,文件后缀必须为dmg. 16GB或者更大的U盘 至少2 ...

  3. 磁盘备份工具dcfldd

    磁盘备份工具dcfldd   dcfldd是Kali Linux自带的一款磁盘备份工具.该工具是dd工具的增强版,更适合渗透测试和安全领域.dcfldd提供实时哈希校验功能,确保数据的安全.同时,它还 ...

  4. 深入解释yield和Generators

    生成器和yield关键字可能是Python里面最强大的最难理解的概念之一(或许没有之一), 但是并不妨碍yield成为Python里面最强大的关键字,对于初学者来讲确实非常难于理解,来看一篇关于yie ...

  5. Sass 和 SCSS 有什么区别?

    Sass 官网上是这样描述 Sass 的: Sass 是一门高于 CSS 的元语言,它能用来清晰地.结构化地描述文件样式,有着比普通 CSS 更加强大的功能. Sass 能够提供更简洁.更优雅的语法, ...

  6. 冒泡排序(高级版)之C++实现

    冒泡排序(高级版)之C++实现 一.源代码:BubbleSortHigh.cpp #include<iostream> using namespace std; /*定义输出一维数组的函数 ...

  7. 关于zip伪加密

    创建一个zip文件 然后用winhex打开 可以看到第二个PK头的地方对应hex区域有一场串0000000000 在这里的第四个0这里末尾修改成奇数 奇数为加密 偶数为不加密 再去打开就可以看到加密了

  8. java多线程技术之条件变量

    上一篇讲述了并发包下的Lock,Lock可以更好的解决线程同步问题,使之更面向对象,并且ReadWriteLock在处理同步时更强大,那么同样,线程间仅仅互斥是不够的,还需要通信,本篇的内容是基于上篇 ...

  9. zookeeper【1】配置管理

    为什么要用统一配置? 我们做项目时用到的配置比如数据库配置等...我们都是写死在项目里面,如果需要更改,那么也是的修改配置文件然后再投产上去,那么问题来了,如果做集群的呢,有100台机器,这时候做修改 ...

  10. Jmeter+JDK的安装学习笔记

    第一步:首先从jmeter的官网下载jmeter,目前最新版本为3.3,支持的JDK最高为1.8 下载地址: jmeter:http://jmeter.apache.org/download_jmet ...