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


我們都是陰溝里的蟲子,但總還是得有人仰望星空。——《三體》

在之前的文章中介紹了Lambda表達式的基本語法正確使用姿勢,這次我來介紹一些Lambda更簡潔的用法。

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

類型推斷

編譯器可以通過函數式接口推斷出Lambda表達式的參數類型,所以在編寫Lambda表達式時,可以省略參數類型。比如:

Comparator<Mask> comparator = (Mask o1, Mask o2) -> o1.getBrand().compareTo(o2.getBrand());

就可以簡寫為:

Comparator<Mask> comparator = (o1, o2) -> o1.getBrand().compareTo(o2.getBrand());

另外,當Lambda表達式只有一個參數的時候,不僅可以省略參數類型,還可以省略到參數名稱兩邊的括號,比如:

Predicate<Mask> predicate = (Mask mask) -> mask.getType() == "N95";

就可以簡寫為:

Predicate<Mask> predicate = mask -> mask.getType() == "N95";

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

方法引用

什么是方法引用?

方法引用是Java8中引入的新特性,它提供了一種引用方法而不執行方法的方式,可以讓我們重復使用現用方法的定義,做為某些Lambda表達式的另一種更簡潔的寫法。

比如前面的例子:

Comparator<Mask> comparator = (o1, o2) -> o1.getBrand().compareTo(o2.getBrand());

使用方法引用以后,可以簡寫為:

Comparator<Mask> comparator = Comparator.comparing(Mask::getBrand);

當你需要方法引用時,目標引用放在分隔符::前,方法的名稱放在分隔符::后。比如,上面的Mask::getBrand,就是引用了Mask中定義的getBrand方法。方法名稱后不需要加括號,因為我們並沒有實際調用它。方法引用提高了代碼的可讀性,也使邏輯更加清晰。

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

怎么構建方法引用?

可以構建方法引用的場景的有四種:

1. 靜態方法

指向靜態方法的引用,語法:類名::靜態方法名,類名放在分隔符::前,:靜態方法名放在分隔符::后。比如:

(String str) -> Integer.parseInt(str)

使用方法引用以后,可以簡寫為:

Integer::parseInt

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

2. 內部對象的實例方法

指向Lambda表達式內部對象的實例方法的引用,語法:類名::實例方法名,類名放在分隔符::前,:實例方法名放在分隔符::后。比如:

(Mask mask) -> mask.getBrand()

使用方法引用以后,可以簡寫為:

Mask::getBrand

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

3. 外部對象的實例方法

指向Lambda表達式外部對象的實例方法的引用,語法:實例名::實例方法名,類名放在分隔符::前,:實例方法名放在分隔符::后。比如:

String type = "N95";
Predicate<String> predicate = (String str) -> type.equals(str);
System.out.println(predicate.test("N95"));

其中,type是一個Lambda表達式外部的局部變量,使用方法引用以后,可以簡寫為:

String type = "N95";
Predicate<String> predicate = type::equals;
System.out.println(predicate.test("N95"));

如果對於Predicate接口還不熟悉,沒關系,以后的文章會介紹到,這里暫且知道它的抽象方法的簽名是(T) -> boolean就可以了。

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。

4. 構造方法

指向構造方法的引用,語法:類名::new,類名放在分隔符::前,new放在分隔符::后。比如:

(String brand, String type) -> new Mask(brand, type)

使用方法引用以后,可以簡寫為:

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技術干貨。

請思考片刻…
.
.
.

.
.
.

宣布答案

  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表達式》系列

歡迎關注微信公眾號:萬貓學社,每周一分享Java技術干貨。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM