死磕Lambda表示式(三):更簡潔的Lambda
阿新 • • 發佈:2020-03-18
>我們都是陰溝裡的蟲子,但總還是得有人仰望星空。——《三體》
在之前的文章中介紹了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技術