Java
終於要支持Lambda表達式!自
年以來Lambda表達式已經在Lambda項目中被支持
在那時候
Lambda表達式仍被稱為Java閉包
在我們進入一些代碼示例以前
先來解釋下為什麼Lambda表達式在Java程序員中廣受歡迎
為什麼使用Lambda表達式
Lambda表達式通常使用在圖形用戶界面(GUI)的開發中
一般來說
GUI編程將程序行為和事件做連接
比如
當用戶按下一個按鈕(觸發一個事件)
你的程序就需要去執行某些行為
可能是將一些數據儲存到一個數據存儲器中
在Swing中
可以使用ActionListener來實現
class ButtonHandler implements ActionListener {
public void actionPerformed(ActionEvent e)
{
//do something
}
}
class UIBuilder {
public UIBuilder() {
button
addActionListener(new ButtonHandler())
}
}
這個例子表明了 ButtonHandler 類作為一個回調替換的用法
在這裡 ButtonHandler 類僅包含 ActionListener 接口定義的 actionPerformed 方法
我們可以使用匿名內部類來簡化代碼
class UIBuilder {
public UIBuilder() {
button
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent event) {
//do something
}
})
}
}
這樣代碼簡潔多了
更仔細的去看代碼時
就會發現我們還創建一個只生成一個實例的類
而這個實例也僅僅持有一個獨立的方法
這恰好是Lambda表達式所能解決的其中一類問題
Lambda表達式代替函數
一個lambda表達式從字面上講就是一個函數
它定義了一個函數的輸入參數和函數體
Java
中的
lambda表達式語法尚未確定
不過大致應該類似這個樣子的
(type parameter)
> function_body 一個具體的例子
(String s
String s
)
> s
length()
s
length()
這個lambda表達式用來計算兩個字符串的長度差
還有一些擴展的語法
比如避免參數的類型定義(我們馬上見看到例子)還有使用{和}來支持多行定義
Collections
sort()
方法是lambda表達的理想例子
它允許我們將字符串按照長度排序
List<String> list = Array
asList(
loooooong
short
tiny
)
Collections
sort(list
(String s
String s
)
> s
length()
s
length())
>
tiny
short
loooooong
所以
不像現在java必須要求的向sort方法輸入一個已經實現的Comparator(比較器)而是傳送一個lambda表達式我們就可以得到相同的結果
Lambda表達式代替閉包
lambda表達式有許多有趣的特性
其中之一是
它們是閉包
一個閉包允許函數訪問直接詞法作用域之外的變量
String outer =
java
(String s
)
> s
length()
outer
length()
在例子中
lambda表達式訪問了字符串 outer 這個作用域之外定義的變量
對於內聯閉包來說這是很難做到的
Lambda表達式也支持類型推論
類型推論是java
引入的但它同樣適用於lambda表達式
簡單來說
類型推論意味著程序員可以在任意一個編譯器能夠自動推斷出類型的地方省略類型定義
如果類型推論能夠應用到前面的排序lambda表達式上
那麼它就能寫成下面的樣子
List<String> list = Arrays
asList(…)
Collections
sort(list
(s
s
)
> s
length()
s
length())
就像你所見到的一樣
參數s
和s
的類型被省略了
因為編譯器知道list是一個字符串集合
它知道被用來作為比較器的lambda表達式必定是相同的類型
因此
這個類型不需要顯式地聲明
即使你有這麼做的自由
類型推論的主要優勢就是減少樣板代碼
如果編譯器可以為我們識別類型
為什麼我們必須自己定義它們
珍愛Lambda表達式
遠離匿名內部類
我們來體會下
為何lambda表達式和類型推論有助於簡化我們前面所提到的回調例子
class UIBuilder {
public UIBuilder() {
button
addActionListener(e
> //process ActionEvent e)
}
}
我們下載直接傳送一個lambda表達式進入 addActionListener 方法來代替前面定義的持有回調方法的類
除了減少模板代碼和提高可讀性以外
它使我們直接表達我們唯一感興趣的事情
處理事件
在我們了解lambda表達式更多優勢之前
先來看看在Scala中的lambda表達式副本
Scala中的Lambda表達式
在函數式編程中
函數是基本的構造塊
Scala融合了java中的面向對象編程和函數式編程
在Scala中
一個lambda表達式是種叫做
函數
或者
函數文本
Scala中的函數屬於一等公民
它們可以被分配給vals或者vars(最終變量或者非最終變量)
它們可以作為其他函數的參數
也可以組合成新的函數
在Scala中一個函數文本寫成如下形式
(argument) => //funtion body
舉例來說
前面提到的java 用來計算兩個字符串長度差的 lambda 表達式
在Scala中寫作如下
(s
: String
s
:String) => s
length
s
length Scala中的函數文本也是閉包
它可以訪問在直接詞法作用域之外定義的變量
val outer =
val myFuncLiteral = (y: Int) => y * outer val result = myFuncLiteral(
) >
這個例子結果是
正如你所見
我們將函數文本分配給了變量 myFuncLiteral
java
的lambda表達式和Scala的函數文本在語法和語義上的相似性是十分明顯的
從語義上講它們是相同的
而語法上的唯一不同就是箭頭符號(java
>
scala =>)和我們沒有提到的簡化符號
From:http://tw.wingwit.com/Article/program/Java/hx/201311/27132.html