1. 程式人生 > >死磕Lambda表示式(三):更簡潔的Lambda

死磕Lambda表示式(三):更簡潔的Lambda

>我們都是陰溝裡的蟲子,但總還是得有人仰望星空。——《三體》 在之前的文章中介紹了Lambda表示式的[基本語法](https://mp.weixin.qq.com/s/ce85WnptSOyQaMBep8L_oA)和[正確使用姿勢](https://mp.weixin.qq.com/s/wW1IWOIxKR_LU0Rf-TaxtA),這次我來介紹一些Lambda更簡潔的用法。 歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。 ### 型別推斷 編譯器可以通過函式式介面推斷出Lambda表示式的引數型別,所以在編寫Lambda表示式時,可以省略引數型別。比如: ```java Comparator comparator = (Mask o1, Mask o2) -> o1.getBrand().compareTo(o2.getBrand()); ``` 就可以簡寫為: ```java Comparator comparator = (o1, o2) -> o1.getBrand().compareTo(o2.getBrand()); ``` 另外,當Lambda表示式只有一個引數的時候,不僅可以省略引數型別,還可以省略到引數名稱兩邊的括號,比如: ```java Predicate predicate = (Mask mask) -> mask.getType() == "N95"; ``` 就可以簡寫為: ```java Predicate predicate = mask -> mask.getType() == "N95"; ``` 歡迎關注微信公眾號:萬貓學社
,每週一分享Java技術乾貨。 ### 方法引用 #### 什麼是方法引用? 方法引用是Java8中引入的新特性,它提供了一種引用方法而不執行方法的方式,可以讓我們重複使用現用方法的定義,做為某些Lambda表示式的另一種更簡潔的寫法。 比如前面的例子: ```java Comparator comparator = (o1, o2) -> o1.getBrand().compareTo(o2.getBrand()); ``` 使用方法引用以後,可以簡寫為: ```java Comparator comparator = Comparator.comparing(Mask::getBrand); ``` 當你需要方法引用時,目標引用放在分隔符`::`前,方法的名稱放在分隔符`::`後。比如,上面的`Mask::getBrand`,就是引用了`Mask`中定義的`getBrand`方法。方法名稱後不需要加括號,因為我們並沒有實際呼叫它。方法引用提高了程式碼的可讀性,也使邏輯更加清晰。 歡迎關注微信公眾號:萬貓學社
,每週一分享Java技術乾貨。 #### 怎麼構建方法引用? 可以構建方法引用的場景的有四種: ##### 1. 靜態方法 指向靜態方法的引用,語法:`類名::靜態方法名`,類名放在分隔符`::`前,:靜態方法名放在分隔符`::`後。比如: ```java (String str) -> Integer.parseInt(str) ``` 使用方法引用以後,可以簡寫為: ```java Integer::parseInt ``` 歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。 ##### 2. 內部物件的例項方法 指向Lambda表示式內部物件的例項方法的引用,語法:`類名::例項方法名`,類名放在分隔符`::`前,:例項方法名放在分隔符`::`後。比如: ```java (Mask mask) ->
mask.getBrand() ``` 使用方法引用以後,可以簡寫為: ```java Mask::getBrand ``` 歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。 ##### 3. 外部物件的例項方法 指向Lambda表示式外部物件的例項方法的引用,語法:`例項名::例項方法名`,類名放在分隔符`::`前,:例項方法名放在分隔符`::`後。比如: ```java String type = "N95"; Predicate predicate = (String str) -> type.equals(str); System.out.println(predicate.test("N95")); ``` 其中,`type`是一個Lambda表示式外部的區域性變數,使用方法引用以後,可以簡寫為: ```java String type = "N95"; Predicate predicate = type::equals; System.out.println(predicate.test("N95")); ``` 如果對於`Predicate`介面還不熟悉,沒關係,以後的文章會介紹到,這裡暫且知道它的抽象方法的簽名是`(T) -> boolean`就可以了。 歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。 ##### 4. 構造方法 指向構造方法的引用,語法:`類名::new`,類名放在分隔符`::`前,`new`放在分隔符`::`後。比如: ```java (String brand, String type) -> new Mask(brand, type) ``` 使用方法引用以後,可以簡寫為: ```java Mask::new ``` #### 小測試 看了這麼多,是不是摩拳擦掌準備試一試了?我們就來一個小測試: 1. `(char[] array) -> new String(array)` 2. `(String str) -> str.length()` 3. `(String type) -> mask.setType(type)`,其中的`mask`是一個`Mask`物件的區域性變數。 4. `(String str) -> System.out.println(str)` 歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。 請思考片刻… . . . ![](https://img-blog.csdnimg.cn/20200103185150176.jpg) . . . **宣佈答案**: 1. 因為`(char[] array) -> new String(array)`是一個構造方法的Lambda表示式,此種方法引用的語法是:`類名::new`,所以正確答案是:`String::new`。 2. 因為`(String str) -> str.length()`是一個內部物件的例項方法的Lambda表示式,此種方法引用的語法是:`類名::例項方法名`,所以正確答案是:`String::length`。 3. 因為`(String type) -> mask.setType(type)`中的`mask`是一個`Mask`物件的區域性變數,它是一個包含外部物件的Lambda表示式,此種方法引用的語法是:`例項名::例項方法名`,所以正確答案是`mask::setType`。 4. 因為`(String str) -> System.out.println(str)`是一個靜態方法的Lambda表示式,此種方法引用的語法是:`類名::靜態方法名`,所以正確答案是`System.out::println`。 怎麼樣?都答對了嘛? 歡迎關注微信公眾號:萬貓學社,每週一分享Java技術乾貨。 ### 《死磕Lambda表示式》系列 - [死磕Lambda表示式(一):初識Lambda](https://mp.weixin.qq.com/s/ce85WnptSOyQaMBep8L_oA) - [死磕Lambda表示式(二):Lambda的使用](https://mp.weixin.qq.com/s/wW1IWOIxKR_LU0Rf-TaxtA) - [死磕Lambda表示式(三):更簡潔的Lambda](https://mp.weixin.qq.com/s/wVlVabABtiLmhmf8WNbyHQ) - [死磕Lambda表示式(四):常用的函式式介面](https://mp.weixin.qq.com/s/5u2P9QFJJ1wR-yT46ysuig) - [死磕Lambda表示式(五):Comparator複合](https://mp.weixin.qq.com/s/AFu_fOFct5kgurIub8MCNw) - [死磕Lambda表示式(六):Consumer、Predicate、Function複合](https://mp.weixin.qq.com/s/CGO59kUQxrngOjthI_3OCQ) 歡迎關注微信公眾號:萬貓學社,每週一分享Java技術