Lambda表达式在Android开发中的应用
来源:互联网 发布:淘宝买家改评价怎么改 编辑:程序博客网 时间:2024/06/07 12:30
上次在盆友圈发了一张照片
上面的两段代码是完全等效的,但是代码行数从11行降低到了一行,更不用说在第一段代码里面,我在run方法的前后以及内部都没有加入任何的空行。由此可以看出,使用lambda可以让你的Java代码在某些情况下达到何等的简洁。那么问题来了。。。
什么叫lambda呢?
Java 8 给我们带来了lambda,然而在Oracle的文档中,我没有找到lambda的定义,wikipedia里面也没有找到适合Java中的lambda的定义。写这篇文章的时候,我在这里 看到一篇很好的介绍lambda的文章,它里面给了一个定义,我觉得还挺合适的。
A lambda expression is a block of code with parameters.
lambda的写法
首先列举一个完整的lambda expression:
(int a, int b) -> { System.out.println("Performing add operation..."); return a+b;}
一个lambda expression由三部分组成:
参数:
(int a, int b)
是这个lambda expression的参数部分,包括参数类型和参数名箭头:
->
代码块:就是用"{}"包含着的那两句代码。
上面说的是一个完整的lambda表达式,在很多情况下,很多东西是可以省略的。比如说,当系统可以根据上下文自动推断出参数的类型的时候,参数类型是可以省略的。这样的话就可以写成:
(a, b) -> { System.out.println("Performing add operation..."); return a+b;}
系统怎么自动推断出参数类型的呢?这个在下面我们就可以看到。
再比如,如果只有一个参数,而参数的类型又可以自动判断,那么连()
也是可以省略的,那么就写成了:
a -> { System.out.println("Performing add operation..."); return a+a;}
再再比如,如果代码块里面只有一行代码,那么{}
也是可以省略的,那么就写成了:
a -> return a+a;
是的,可以写在同一行
a -> return a+a;
让我们更进一步,在这里,return
其实也是没必要的。
a -> a+a;
Great, 如果没有参数的话,是不是就可以写成:
-> a+a
呢?
很可惜,答案是否定的。如果没有参数,那么前面的()
是必须存在的。也就是说,必须写成:
()-> a+a
lambda的用法
实际上,如果你直接把上面的代码放到你的编辑器里面,你的IDE是会报错的,因为lambda是不能这样使用的。lambda的使用永远要跟一个叫做Functional Interface
的东西绑定在一起。什么叫Functional Interface
呢?Functional Interface
也是Java8 中引入的概念.是的,是为了lambda。我们知道java中的interface
,而Functional Interface
其实就是一个只定义了一个抽象方法的interface
。比如Runnable
这个interface就只有一个run方法,那么它就是一个Functional Interface
。
如果你对“重复”这件事情比较敏感的话,你可能又有疑问了,什么叫只定义了一个抽象方法的interface?interface中的方法不都是抽象的吗?你这个是病句吧,重复了。。。Well,在java8以前是这样的,然而在java8中,Java引进了default method的概念,说白了就是带有具体实现的方法:
public interface DuckInterface { public void wwwalksLikeADuck(); public default void tttalksLikeADuck() { System.out.println("Quack!"); }}
在上面的例子中,tttalksLikeADuck()
就是一个default method,注意到这个方法的定义中有一个“default”修饰符。相信很多人会觉得这是个非常有用的feature,我也是这样觉得的。
再说回Functional Interfacel和lambda。刚刚说到,lambda必须和Functional Interface配套使用,那怎么配套使用呢?
以安卓里面的View.OnClickListener为例(它也是个Functional Interface)如果没有lambda,我们经常会这样使用的。
View.OnClickListener onClickListener = new View.OnClickListener() { @Override public void onClick(View view) { handleClick(); }});findViewById(R.id.someView).setOnClickListener(onClickListener);
或者直接使用匿名内部类:
findViewById(R.id.someView).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { handleClick(); }});
在上面的5行代码中,有用的其实只有handleClick()
,而我们却必须用5行代码去处理,这是非常繁琐的。在Java 8以前的世界,这样的代码非常多。有一个专门的名词来称呼这种性质的代码,叫“boilerplate code”,我不知到中文叫什么。。。
现在好了,有了lambda,我们可以这样写:
View.OnClickListener onClickListener = view -> handleClick();findViewById(R.id.someView).setOnClickListener(onClickListener);
匿名内部类的版本:
findViewById(R.id.someView).setOnClickListener(view -> handleClick());
是不是瞬间觉得简洁优雅了?从上面的例子可以看到,lambda其实就相当于简化了Functional Interface的实例的创建。当然,从真正意义上来讲,lambda的意义不止这么一点点,只不过从使用的角度来看,你可以这样看待。
从lambda到Functional Programming
这里稍微讨论一下关于lambda的其他一些特性。在上面的例子中
View.OnClickListener onClickListener = view -> handleClick();findViewById(R.id.someView).setOnClickListener(onClickListener);
这里,你既可以吧onClickListener看作是OnClickListener的一个instance,也可以把它看做一个代码块,后面的那句findViewById(R.id.someView).setOnClickListener(onClickListener);
就相当于是吧这个代码块传给了view.setOnClickListener()这个函数。也就是说,从某种意义上来讲,你可以把lambda看作是可以相互传递的代码块。而传递代码块,是Functional Programming(一下简称FP)非常重要的一个特征,虽然说这两者其实没有什么对等关系。因为FP的本质特征是,运行一段代码并不会改变事物的状态,也就是说,没有side-effect。而lambda里面是可以调用所在的类的成员方法的、也可以访问和修改所在类的成员变量的。
话说回来,关于FP我也不是了解的很多,我本身并没有多少FP的经验,虽然对Ruby有一定了解,但Ruby也只是“可以比较好的进行”FP而已,也不是纯粹的FP语言。纯粹的FP语言是List(包括Scheme,Clojure)、Haskell、ML等等这些。关于FP,Robert Martin(就是《Clean code》和《The Clean Coder》的作者)有一个讲得很好的视频在这里。
刚刚讲到,lambda的代码块可以访问所在类的成员变量和成员方法,那对于局部变量?
我们知道,方法内部定义的匿名类是可以访问所在方法的final局部变量的,作为Functional Interface的简写方式,lambda在这点上面跟匿名类保持了一致。也就是说,lambda可以访问定义它的那个方法的final局部变量。而在Java8里面,lambda还可以访问所谓“Effectively final”的局部变量。所谓“Effectively final”的局部变量,就是说除了在定义的时候给了一个初始值以为,在没有改变过她的值的那些局部变量:
int age = 26; //在这里,age就是Effectively final的局部变量Runnable r = () -> System.out.println("My age is "+age);new Thread(r).start();
在Android开发中的应用
可是!!!Android只支持Java 7啊?怎么办?莫急,要相信网友的力量,已经有人开发了gradle的插件,可以将java 8中的labmda表达式在编译出来的bytecode里面,给它转化成Java 7兼容的代码。猛戳这里,使用方法那个页面都用,在这里就不赘述了。
- Lambda表达式在Android开发中的应用
- Lambda表达式在Android中的应用
- Lambda表达式在linq中的应用
- java8 lambda表达式在集合中的应用
- Java 8的Lambda及其在Android 开发中的应用
- Lambda表达式在游戏开发中应用
- Lambda表达式在Android中的使用
- Lambda表达式在Android中的使用
- lambda:在android studio中的配置和使用lambda表达式
- python3 lambda 表达式以及在map函数中的应用
- lambda表达式-java中的应用
- 关于lambda表达式在Android Studio中的使用
- 在android使用lambda表达式
- lambda在C++中的应用
- Lambda在Comparator中的应用
- 正则表达式在IOS开发中的应用
- Lambda在Android中的使用
- Lambda表达式在安卓中的使用
- 【caffe源码研究】第三章:源码篇(4) :Solver
- 设计模式--[7]解释器模式
- string与new string跟StringBuffer和StringBuilder的区别
- Android_聊一聊Activity(一)
- Ajax用jsonp方式跨域发送请求
- Lambda表达式在Android开发中的应用
- Android菜鸟练习第三十五课 Service基本使用
- android studio 获取SHA1(指纹)
- Eclipse启动Tomcat错误:Several ports (8080, 8009) required by Tomcat v6.0 Server at localhost are already
- AndroidStudio 错误:Read-Only Status of Files
- Hadoop YARN中内存和CPU两种资源的调度和隔离
- 一个解决中午吃什么去哪吃的程序
- 对话框进度条——ProgressDialog
- 评委打分