Java 8實戰 第三章
Lambda函數特點:
- 匿名——寫得少想的多。
- 函數——lambda有參數列表、函數主體、返回類型,有可以拋出的異常列表。
- 傳遞——lambda表達式可作為參數傳遞給方法或存儲在變量中。
- 簡介
Lambda隱含return語句(可以顯式地使用return)。
Lambda有三個部分(更多示例: http://www.cnblogs.com/Hu-Yan/p/7955550.html)
- 參數列表
- 箭頭
- Lambda主體
return是一個控制流語句,要使它在lambda表達式中有效需要使用{}。
" ExampleString "是一個表達式,不是一個語句,要使它在lambda表達式中有效需要去除{} 和 ;
函數式接口:只定義一個抽象方法的接口(即使接口中還含有默認方法)。註意該接口是否繼承了別的方法。
Lambda函數允許你直接以內聯的形式為函數式接口的抽象方法提供實現, 並把整個表達式作為函數式接口的實例。
函數式接口的抽象方法的簽名基本上是lambda表達式的簽名。這種抽象方法叫做函數描述符。簽名匹配,lambda表達式才會有效。
常見的函數式接口:Comparable, Runnable, Callable, Predicate, Consumer, Function …
在你需要表示一個涉及類型T的布爾表達式時,則可以使用Predicate接口。
如果需要訪問類型T的對象,並對其執行某些操作,則可以使用Consumer接口(抽象方法:accept,接受泛型的對象,無返回。)。
如果需要將輸入對象的信息映射到輸出,則可以使用Function接口,它定義了apply方法——接受一個泛型T的對象並返回一個泛型R的對象。
裝箱(boxing)機制:Java類型要麽是引用類型,要麽是原始類型。但是泛型只能綁定到引用類型。拆箱(unboxing):將 引用類型轉換為對應的原始類型。
裝箱後的值需要更多內存,並需要額外內存搜索來獲取被包裹的原始值。
針對專門的輸入參數類型的函數式接口的名稱都要加上相對應的原始類型。如:DoublePredicate、IntConsumer … Function接口還有針對輸出參數類型的變種: ToIntFunction<T> 等。
使用案例 | 對應函數式接口 |
布爾表達式 | Predicate |
創建對象 | Supplier |
使用一個對象 | Consumer |
從一個對象中選擇/提取 | Function / ToIntFunction |
合並兩個值 | intBinaryOperator |
比較兩個對象 | Comparator / BiFunction / ToIntBiFunction |
任何函數式接口都不允許拋出受檢異常(checked exception)。如果你需要lambda表達式拋出異常,有兩種方法:
- 自定義一個函數式接口, 並聲明受檢異常。
- 把lambda表達式辦函在一個try/catch塊中。
Lambda表達式需要的類型稱為目標類型。其類型檢查過程如下所示:
- 找出方法的聲明
- 要求它是目標類型的第二個正式參數。
- 函數式接口定義了一個抽象方法
- 該抽象方法描述了一個函數描述符
- 方法的任何實際參數都需匹配這個要求。
Caution:如果lambda函數拋出異常,那麽抽象方法所聲明的throws語句必須與之匹配。
同一個Lambda表達式可以與不同的函數式接口聯系起來,只要它們的抽象方法簽名能夠兼容。
如果一個Lambda的主體是一個語句表達式,他就和一個返回void的函數描述符兼容。
當Lambda僅有一個類型需要推斷的參數時,參數名稱的兩邊的括號也可以省略。
方法引用的基本思想:如果一個lambda表達的知識"直接調用這個方法",那最好還是用名稱來調用它,而不是去描述如何調用它。
方法引用的使用:目標引用放在分隔符::前,方法的名稱放在後面。
方法引用主要有三種:
- object::instanceMethod(指向現有對象的實例方法的引用,其思想是——調用一個已存在的外部對象的方法)
- ClassName::staticMethod(指向靜態方法的方法引用)
- ClassName::instanceMethod(指向任意類型實例方法的方法引用,思想為——引用一個對象的方法,而這個對象本身是lambda的一個參數。)
Lambda表達式重構等價的方法引用 :
Lambda | 方法引用 |
(arg0, rest) -> arg0.instanceMethod(rest) | ClassName :: instanceMethod |
Lambda | 方法引用 |
(args) -> ClassName.staticMethod(args) | ClassName :: staticMethod |
Lambda | 方法引用 |
(ags) -> expr.instanceMethod(args) | expr :: instanceMethod |
方法引用的簽名必須和上下文類型匹配。
創建一個構造函數的引用——ClassName :: new
構造函數參數個數 | 使用構造函數引用 |
1 | Supplier<T> |
2 | Function<T, R> |
3 | BiFunction<T, U, R> |
>= 4 |
Java 8實戰 第三章