1. 程式人生 > >JDK8 ——lambda表示式

JDK8 ——lambda表示式

1、為什麼要使用lambda表示式

lambda表示式是一段可以傳遞的程式碼,因此它可以被執行一次或多次。

在jdk8之前,向其他程式碼傳遞一段程式碼不是很容易,我們不能將程式碼塊到處傳遞。我們需要構建一個屬於某個類的物件,由它的某個方法來包含所需的程式碼。在其他一些語言中可以直接使用程式碼塊。在過去的很長一段時間裡,java設計者們都拒絕加入這一特性。java的優勢本就在於他的簡單和一致性。如果加入可以略微簡化的程式碼,其將不易於維護。當然,還有一方面是,其他語言有大量的簡單、一致、強大的API,java中的API卻沒有能達到這種效果。

基於以上,最近一段時間,大家不再討論是否需要使用了,而是在討論該怎麼實現。並且很可喜的是,在jdk8中已經做了實現。

2、lambda表示式的語法

其格式為:引數、箭頭->,以及一個表示式。如果相關程式碼無法用一個表示式表示,可以用編寫方法的方式編寫:既可以使用{}包裹程式碼並明確使用return語句。

如一個做比較的表示式可以這麼寫:

Comparator<String> comp = (String first, String second) -> Integer.compare(first.length(), second.length());
如果lambda表示式沒有引數,可以提供一對空的小括號,如同不含引數的方法那樣。

如果一個表示式的引數型別是可以被推導是,可以省略它們的型別。比如上面的String fisrt及後面的second的String引數都是可以不要的。

永遠不需要為lambda表示式執行返回型別,它總是會從上下文中被推匯出來。

3、函式式介面

對於只包含一個抽象方法的介面,可以通過lamba表示式來建立該介面的物件。

4、方法引用

當想要傳遞給其他程式碼的操作已經有了實現的方法,就可以使用方法引用。方法引用有三種主要的使用情況:

a、物件::例項方法

b、類::靜態方法

c、類::例項方法

5、構造器引用

構造器引用同方法引用類似,不同的是在構造器引用中方法名是new。

如Button::new表示Button類的構造器引用。對於擁有多個構造器的類,選擇使用哪個構造器取決於上下文。

6、變數作用域

通常,我們希望可以在lambda表示式的閉合方法或類中訪問其他的變數。

一個lambda表示式包括三個部分:

a、一段程式碼;b、引數;c、自由變數的值,自由指的是那些不是引數並且沒有在程式碼中定義的變數。

lambda表示式可以捕獲閉合作用域中的變數值,由此需要遵守一個約束,在lambda表示式中被引用的變數的值不可以被更改。更改lambda表示式中的變數不是執行緒安全的。

lambda表示式的方法體與巢狀程式碼塊有著相同的作用域。也適用於同樣的命名衝突和遮蔽規則。即不允許宣告一個與區域性變數同名的引數或者區域性變數。不能有兩個同名的區域性變數。在lambda中使用this關鍵字時,會引用建立該lambda表示式的方法的this關鍵字。

7、預設方法

許多開發語言都將函式表示式整合到了其集合庫中。

如果一個介面中定義了一個預設方法,而另外一個父類或介面中又定義一個同名的方法,該選擇哪個?java中的規則如下:

a、選擇父類中的方法。如果一個父類提供了具體的實現方法,那麼介面中具有相同名稱和引數的預設方法會被忽略。

b、介面衝突。如果一個父介面提供了一個預設方法,而另一個介面也提供了一個具有相同名稱和引數型別的方法(不管該方法是否是預設方法),那麼你必須通過覆蓋該方法類解決衝突。

如此設計是為了實現“類優先”的規則,並且可以和之前的設計相相容,不會因為在新介面中添加了一個預設方法,就導致跟之前版本不相容了。

8、介面中的靜態方法

在jdk8中,可以為介面新增靜態方法。從技術角度來說,這是完全合法的。只是它看起來違反了介面作為一個抽象定義的理念。

在jdk8中,很多介面已經添加了靜態方法。c