上次在盆友圈发了一张照片java
上面的两段代码是彻底等效的,可是代码行数从11行下降到了一行,更不用说在第一段代码里面,我在run方法的先后以及内部都没有加入任何的空行。由此能够看出,使用lambda可让你的Java代码在某些状况下达到何等的简洁。
那么问题来了。。。git
Java 8 给咱们带来了lambda,然而在Oracle的文档中,我没有找到lambda的定义,wikipedia里面也没有找到适合Java中的lambda的定义。写这篇文章的时候,我在这里 看到一篇很好的介绍lambda的文章,它里面给了一个定义,我以为还挺合适的。github
A lambda expression is a block of code with parameters.express
首先列举一个完整的lambda expression:jvm
(int a, int b) -> { System.out.println("Performing add operation..."); return a+b; }
一个lambda expression由三部分组成:编辑器
参数:(int a, int b)
是这个lambda expression的参数部分,包括参数类型和参数名ide
箭头:->
函数
代码块:就是用"{}"包含着的那两句代码。gradle
上面说的是一个完整的lambda表达式,在不少状况下,不少东西是能够省略的。好比说,当系统能够根据上下文自动推断出参数的类型的时候,参数类型是能够省略的。这样的话就能够写成:spa
(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
实际上,若是你直接把上面的代码放到你的编辑器里面,你的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的其余一些特性。
在上面的例子中
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只支持Java 7啊?怎么办?莫急,要相信网友的力量,已经有人开发了gradle的插件,能够将java 8中的labmda表达式在编译出来的bytecode里面,给它转化成Java 7兼容的代码。猛戳这里,使用方法那个页面都用,在这里就不赘述了。
若是对文章有任何意见或建议,或者是发现文中有任何问题欢迎留言!