在JDK8和ES6的语言发展中,在Java的lambda表达式和JavaScript的箭头函数这二者有着千丝万缕的联系;本次试图经过这篇文章弄懂上面的两个“语法糖”。javascript
Lambda 表达式来源于 C# 5.0,但又不太肯定,因而查了下 百度百科:Lambda表达式,仍然没有获得明确的答案,因此懒得去纠结这个问题了。html
箭头函数(arrow function),就是C#中的lambda表达式,听说Java8也把它加入了。但无论怎样,JS正在从其它语言吸纳优秀的特性(好比yield, class, 默认参数等等),且不论这些特性好坏,这件事自己就是极好的(至少咱们正在使用的是一个充满活力的工具)java
只是Java用->
箭头,C#用的箭头与JS同样:=>
,这个箭头叫“lambda运算符”,行话读做”goes to”git
lambda表达式(箭头函数)听说是定义函数最简洁的方法,语法上几乎没有冗余成分了。由于JS弱类型的特色,JS中的lambda表达式要比C#和Java中的更简洁(少了参数类型声明)github
一句话,箭头函数就是lambda表达式,提供了更简洁的function定义方式express
这里先给简要的定义:将匿名函数复制给变量的简写方式的函数称为 lambda 表达式。编程
一、java的场景中:把“一块代码”赋给一个Java变量ide
这个是简化过程:
函数式编程
二、JS中同理也是比较简单的函数
var fun1 = funcation(int x,int y){ return (x+y); }
简写以下:
var fun1 = (x,y)=>x+y;
这里因为Java一切皆对象的缘由,暂时先介绍JavaScript的定义,但Java基本雷同
Lambda 表达式的主要形式是以下定义,符号的左侧是参数,右侧是表达式或语句块。
(参数列表) => { 语句块 }
当“语句块”只有一条语句的时候,能够省略大括号,就成了
(参数列表) => 语句
注意: Lambda 表达式通常是做为参数或者值使用,因此根据使用的上下文,大部分状况下编译器能够推断出 Lambda 表达式的参数类型;Lambda 表达式的参数一般是省略类型的
Lambda 表达式的做用其实就是匿名方法,而 Java 中并无匿名方法这一语法。不过 Java 中有匿名对象,当你直接 new 一个接口并实现接口方法的时候,Java 编译器实际是产生了一个类(匿名类)来实现这个接口,而后再返回这个类的一个实例,也就是匿名对象;Lambda表达式自己就是一个接口的实现。
这种只有一个接口函数须要被实现的接口类型,咱们叫它”函数式接口“。为了不后来的人在这个接口中增长接口函数致使其有多个接口函数须要被实现,变成"非函数接口”,咱们能够在这个上面加上一个声明@FunctionalInterface, 这样别人就没法在里面添加新的接口函数了:
下面是一个完整的案例:
@FunctionalInterface public interface WorkerInterface { public void doSomeWork(); } public class WorkerInterfaceTest { public static void execute(WorkerInterface worker) { worker.doSomeWork(); } public static void main(String [] args) { //invoke doSomeWork using Annonymous class execute(new WorkerInterface() { @Override public void doSomeWork() { System.out.println("Worker invoked using Anonymous class"); } }); //invoke doSomeWork using Lambda expression execute( () -> System.out.println("Worker invoked using Lambda expression") ); } }
上面经过两个简单的案例演示了lambda,如今总结一下在Java和JavaScript常见的用法和使用常见。
JAVA8中就提供了这种“函数式编程”的方法 —— lambda表达式,供咱们来更加简明扼要的实现内部匿名类的功能。
函数式接口:Functional Interface.
定义的一个接口,接口里面必须 有且只有一个抽象方法 ,这样的接口就成为函数式接口。
在可使用lambda表达式的地方,方法声明时必须包含一个函数式的接口。
简单的说,凡是(java8以上)函数式接口均可以尽可能使用lambda表达式,注意:若是咱们提供的这个接口包含一个以上的Abstract Method,那么使用lambda表达式则会报错。建议定义的接口加上@FunctionalInterface
注解。
根据以前的思路;只要找到Java中函数式接口的皆能够放出lambda表达式
的大招。
JDK 8以前已有的函数式接口
java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener
Java SE 8中增长了一个新的包:java.util.function,它里面包含了经常使用的函数式接口:
补充: 关于函数式接口的详细总结
1)Java8中Iterable的foreach(Comsumer action)的函数式接口
2)Java8中Iteror的forEachRemaining(Comsumer action)的函数式接口
3)Java8中函数式接口Predicate;Collections的removeIf(Predicate filter)
...其实还有不少,就不一一列举了,其实根据规则就很容易了加上编译器优化,其实写出lambda其实也是很容易。
因为JavaScript基于函数编程,lambda表达式很是灵活经常使用,基本上对于参数的简单操做均可以使用箭头函数完成,这里能够告诉你不要试图滥用。
参考资料