在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表達式很是靈活經常使用,基本上對於參數的簡單操做均可以使用箭頭函數完成,這裏能夠告訴你不要試圖濫用。
參考資料