(4.6.24)Lambda表达式 in Android
来源:互联网 发布:mysql 余数 编辑:程序博客网 时间:2024/06/03 20:35
- 引入
- 使用Lambda在Android中替代匿名类
- 基本语法
- 官方示例
- 设置监听事件
- 实现Runnable
- 函数式接口Functional interfaces
- Lambda和匿名内部类的区别
- 参考文献
就目前而言,Lambda的向后兼容性和稳定性都是不可预测和无法保障的,因此并不建议在企业项目中使用
引入
为了支持函数式编程,Java 8引入了Lambda表达式,Android N已经开始支持Java 8 了。使用Lambda可以大大减少代码的编写,只关注最重要的部分(形参和函数体),虽然使代码的可读性变差,但用习惯了就会喜欢上Lambda表达式,它使代码变得干净整洁了不是一点半点。
Lambda表达式取代了匿名类,取消了模板,允许用函数式风格编写代码.
在Android中使用Lambda需要使用jdk8.0,如果想在6.7中使用可以引入下插件:gradle-retrolambda
A gradle plugin for getting java lambda support in java 6, 7 and android
使用Lambda在Android中替代匿名类
基本语法
(parameters) -> { expression or statements }
下面是一些例子:
// 无参数, 返回1+2的结果 () -> 1+2 // 接收一个参数(数字类型),返回其2倍的值 x -> 2 * x// 接收2个参数(数字),返回表达式运算的结果 (x, y) -> x + y// 多个语句要用大括号包裹, 并且返回值要用return指明(x, y) -> { int result = x + y; System.out.print(result); return result;}// 接收string 对象, 并在控制台打印 s -> System.out.print(s)
其中参数的类型可以不声明, 编译器会结合上下文智能推断, 比如这句
s -> System.out.print(s)//等价于(String s) -> System.out.print(s)
注意: 无参数时()不能省略
官方示例
设置监听事件
Android中我们设置监听一般这么写:
mFab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doSomething(); } });
那么用Lambda可以如何写呢?
mFab.setOnClickListener(v->doSomething());
整个匿名内部类被v->doSomething()给代替了. 本例子中的v
代表onClick传递的参数v,参数不能省略,但是可以随意命名.
实现Runnable
在Android中我们起个线程一般这么写:
new Thread(new Runnable() { @Override public void run() { doSomething(); } }).start();
而使用Lambda表达式的话可以这么写:
new Thread(() -> doSomething()).start();
另外实例化Runnable成员变量也可以这么写:
Runnable runnable = ()->doSomething();
函数式接口(Functional interfaces)
能用Lambda表达式替代的匿名内部类有两个条件: 必须是接口类型; 只有一个抽象方法.
Lambda和匿名内部类的区别
看起来Lambda表达式只是简化了匿名内部类的书写, 事实上Lambda并非匿名内部类的语法糖, Lambda的效率比匿名内部类要高.
以下内容主要学习自深入探索Java 8 Lambda表达式
我们依旧使用前面自定义Lambda表达式的例子研究, 先来看匿名内部类的代码:
public class LambdaDemo { public static void main(String[] args) { Person person = new Person("Smarx", 23); printPerson(person, new IPersonPrinter() { public void printPerson(Person p) { System.out.println(p.toString()); } }); } private static void printPerson(Person p, IPersonPrinter personPrinter){ personPrinter.printPerson(p); }}
进入这个文件所在的目录, 使用命令行编译
javac LambdaDemo.java
再使用javap命令查看字节码
javap -c -v LambdaDemo
可以看到匿名内部类生成的字节码如下:
12: aload_113: new #5 // class LambdaDemo$116: dup17: invokespecial #6 // Method LambdaDemo$1."<init>":()V20: invokestatic #7 // Method printPerson:(LPerson;LIPersonPrinter;)V23: return
上述字节码的含义如下:
- 第13行,使用字节码操作new创建了类型LambdaDemo$1的一个对象,同时将新创建的对象的的引用压入栈中。
- 第16行,使用dup操作复制栈上的引用。
- 第17行,上面的复制的引用被指令invokespecial消耗使用,用来初始化匿名内部类实例。
- 第20行,调用本类的静态方法printPerson
将匿名内部类改写成Lambda,重新编译后再查看字节码
12: aload_113: invokedynamic #5, 0 // InvokeDynamic #0:printPerson:()LIPersonPrinter;18: invokestatic #6 // Method printPerson:(LPerson;LIPersonPrinter;)V21: return
可以看到字节码与匿名内部类的版本并不相同, Lambda表达式转化成字节码实际上做了如下两步:
- 生成一个invokedynamic调用点,也叫做Lambda工厂。当调用时返回一个Lambda表达式转化成的函数式接口实例。
- 将Lambda表达式的方法体转换成方法供invokedynamic指令调用。
也就是说, Lambda表达式其实被翻译成了本类的一个静态方法, 比如我们上面的代码, 会被翻译成类似这样的方法:
static void lambda$1(String s){ System.out.println(p.toString());}
需要注意的是,这里的$1并不是代表内部类,这里仅仅是为了展示编译后的代码而已。
需要注意的是编译器对于Lambda表达式的翻译策略并非固定的,因为这样invokedynamic可以使编译器在后期使用不同的翻译实现策略。比如,被捕获的变量可以放入数组中。如果Lambda表达式用到了类的实例的属性,其对应生成的方法可以是实例方法,而不是静态方法,这样可以避免传入多余的参数。
参考文献
- Java SE 8: Lambda Quick Start
- Java8 lambda表达式10个示例
- 是时候学习一波Lambda表达式了
- 深入浅出 Java 8 Lambda 表达式
- 理解Java 8 Lambda(语言篇——lambda,方法引用,目标类型和默认方法)
- (4.6.24)Lambda表达式 in Android
- 【Android】Lambda表达式
- 【android】 lambda表达式
- lambda 表达式 android
- Android Lambda表达式
- lambda表达式(一)
- ()-> java8:Lambda表达式
- Android 中使用Lambda表达式
- 在android使用lambda表达式
- Android中使用lambda表达式
- Android中使用lambda表达式
- Android studio使用lambda表达式
- Android Studio 使用Lambda表达式
- Android Studio 使用 Lambda表达式
- Android 中使用lambda表达式
- Android 中使用Lambda表达式
- Android Studio 引入Lambda表达式
- Android 中使用Lambda表达式
- HBase scan超时
- 阿里云服务器部署Windows的php环境
- 用ExportToXls方法导出到Excel就变成这样一团的解决方法
- Makefile,自动搜索源文件并编译
- 【JPA】 级联注解的解释 @Cascade
- (4.6.24)Lambda表达式 in Android
- C语言在VS2017环境下写俄罗斯方块的感悟
- iOS远程通知
- Elasticsearch+Hbase实现海量数据秒回查询
- linux centos7安装tomcat7以及遇到坑的解决办法
- Ubuntu 配置qt5.9.1 android 开发环境(简单记录)
- 索引数据删除
- easyUI使用总结
- 使用FastDFS搭建图片服务器单实例篇