Java 8 中的方法引用妄帘,輕松減少代碼量澈吨,提升可讀性!

1. 引言

Java8中最受廣大開發(fā)中喜歡的變化之一是因?yàn)橐肓?lambda 表達(dá)式寄摆,因?yàn)檫@些表達(dá)式允許我們放棄匿名類谅辣,從而大大減少了樣板代碼,并提高了可讀性婶恼。
方法引用是lambda表達(dá)式的一種特殊類型桑阶。它們通常通過引用現(xiàn)有方法來創(chuàng)建簡單的lambda表達(dá)式。

方法引用包括以下四種類型:

  • 靜態(tài)方法
  • 特定對(duì)象的實(shí)例方法
  • 特定類型的任意對(duì)象的實(shí)例方法
  • 構(gòu)造方法

在本篇文章中勾邦,我們將探討Java中的方法引用蚣录。

2. 引用靜態(tài)方法

We'll begin with a very simple example, capitalizing and printing a list of Strings:

我們從一個(gè)非常簡單的示例開始,字符串轉(zhuǎn)成大寫并打泳炱:

List<String> messages = Arrays.asList("hello", "baeldung", "readers!");

我們可以通過簡單的lambda表達(dá)式直接調(diào)用 StringUtils.capitalize() 方法:

messages.forEach(word -> StringUtils.capitalize(word));

或者萎河,我們可以使用方法引用來簡單地引用 capitalize 靜態(tài)方法:

messages.forEach(StringUtils::capitalize);

注意,方法引用應(yīng)使用::運(yùn)算符。

3. 引用特定對(duì)象的實(shí)例方法

為了演示這種類型的方法引用虐杯,我們新建以下這兩個(gè)類:

public class Bicycle {
 
    private String brand;
    private Integer frameSize;
    // standard constructor, getters and setters
}
 
public class BicycleComparator implements Comparator {
 
    @Override
    public int compare(Bicycle a, Bicycle b) {
        return a.getFrameSize().compareTo(b.getFrameSize());
    }
 
}

創(chuàng)建一個(gè) BicycleComparator 對(duì)象來比較自行車尺寸:

BicycleComparator bikeFrameSizeComparator = new BicycleComparator();

我們可以使用lambda表達(dá)式按尺寸大小對(duì)自行車進(jìn)行排序玛歌,但需要指定兩個(gè)自行車實(shí)例進(jìn)行比較:

createBicyclesList().stream()
  .sorted((a, b) -> bikeFrameSizeComparator.compare(a, b));

我們可以使用方法引用讓編譯器把句柄參數(shù)傳遞給我們:

createBicyclesList().stream()
  .sorted(bikeFrameSizeComparator::compare);

4. 引用特定類型任意對(duì)象的實(shí)例方法

這種類型的方法引用與前面的示例類似,但不必創(chuàng)建自定義對(duì)象來執(zhí)行比較擎椰。

讓我們創(chuàng)建一個(gè)要排序的Integer 整數(shù)列表:

List<Integer> numbers = Arrays.asList(5, 3, 50, 24, 40, 2, 9, 18);

如果我們使用經(jīng)典的 lambda 表達(dá)式支子,這兩個(gè)參數(shù)都需要顯式傳遞,而使用方法引用則要簡單得多:

numbers.stream()
  .sorted((a, b) -> a.compareTo(b));
numbers.stream()
  .sorted(Integer::compareTo);

盡管它仍然是一行代碼达舒,但是方法引用更容易閱讀和理解值朋。

5. 引用構(gòu)造函數(shù)

我們可以像在第一個(gè)例子中引用靜態(tài)方法一樣引用構(gòu)造函數(shù)。唯一區(qū)別是需要使用new關(guān)鍵字巩搏。
現(xiàn)在我們用不同品牌的String列表創(chuàng)建一個(gè)Bicycle數(shù)組:

List<String> bikeBrands = Arrays.asList("Giant", "Scott", "Trek", "GT");

首先昨登,我們將向Bicycle類添加一個(gè)新的構(gòu)造函數(shù):

public Bicycle(String brand) {
    this.brand = brand;
    this.frameSize = 0;
}

接下來,我們將使用方法引用中的新構(gòu)造函數(shù)贯底,并從原始的String列表中生成一個(gè)Bicycle數(shù)組:

bikeBrands.stream()
  .map(Bicycle::new)
  .toArray(Bicycle[]::new);

注意如何使用方法引用調(diào)用BicycleArray構(gòu)造函數(shù)丰辣,從而使代碼看起來更加簡潔明了。

6. 其他示例和限制

目前為止丈甸,方法引用是一個(gè)使代碼非常清晰和易讀的好方法糯俗。但是尿褪,我們不能用它們來代替各種lambda表達(dá)式睦擂,因?yàn)樗鼈冇幸恍┚窒扌浴?/p>

它們的主要局限性是由于它們最大的優(yōu)點(diǎn):前一個(gè)表達(dá)式的輸出需要與引用的方法聲明的輸入?yún)?shù)匹配

看看這個(gè)限制的例子:

createBicyclesList().forEach(b -> System.out.printf(
  "Bike brand is '%s' and frame size is '%d'%n",
  b.getBrand(),
  b.getFrameSize()));

這個(gè)簡單的例子不能用方法引用來表示杖玲,因?yàn)樵谖覀兊睦又校?em>printf 方法需要3個(gè)參數(shù)顿仇,而使用createBicyclesList().forEach()只允許方法引用一個(gè)參數(shù)(Bicycle對(duì)象)。

最后摆马,我們研究下臼闻,如何創(chuàng)建一個(gè)可以從lambda表達(dá)式引用的no-operation函數(shù)。

在本例中囤采,我們希望使用lambda表達(dá)式而不使用其參數(shù)述呐。

首先,創(chuàng)建 doNothingAtAll 方法:

private static <T> void doNothingAtAll(Object... o) {
}

因?yàn)檫@是一個(gè)varargs方法蕉毯,它可執(zhí)行在任意 lambda 表達(dá)式中乓搬,而不管引用的對(duì)象或參數(shù)的數(shù)量。我們看看它的作用:

createBicyclesList()
  .forEach((o) -> MethodReferenceExamples.doNothingAtAll(o));

7. 總結(jié)

在這篇文章中代虾,我們學(xué)習(xí)了Java中的方法引用进肯,以及如何使用它們來替換lambda表達(dá)式,從而提高了可讀性并闡明編程的意圖棉磨。

如果你覺得文章還不錯(cuò)江掩,記得關(guān)注公眾號(hào): 鍋外的大佬
鍋外的大佬博客

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子环形,更是在濱河造成了極大的恐慌策泣,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件斟赚,死亡現(xiàn)場離奇詭異着降,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拗军,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門任洞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人发侵,你說我怎么就攤上這事交掏。” “怎么了刃鳄?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵盅弛,是天一觀的道長。 經(jīng)常有香客問我叔锐,道長挪鹏,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任愉烙,我火速辦了婚禮讨盒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘步责。我一直安慰自己返顺,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布蔓肯。 她就那樣靜靜地躺著遂鹊,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蔗包。 梳的紋絲不亂的頭發(fā)上秉扑,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音调限,去河邊找鬼舟陆。 笑死,一個(gè)胖子當(dāng)著我的面吹牛旧噪,可吹牛的內(nèi)容都是我干的吨娜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼淘钟,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼宦赠!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤勾扭,失蹤者是張志新(化名)和其女友劉穎毡琉,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體妙色,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡桅滋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了身辨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丐谋。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖煌珊,靈堂內(nèi)的尸體忽然破棺而出号俐,到底是詐尸還是另有隱情,我是刑警寧澤定庵,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布吏饿,位于F島的核電站,受9級(jí)特大地震影響蔬浙,放射性物質(zhì)發(fā)生泄漏猪落。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一畴博、第九天 我趴在偏房一處隱蔽的房頂上張望笨忌。 院中可真熱鬧,春花似錦绎晃、人聲如沸蜜唾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至擎勘,卻和暖如春咱揍,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背棚饵。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來泰國打工煤裙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人噪漾。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓硼砰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親欣硼。 傳聞我的和親對(duì)象是個(gè)殘疾皇子题翰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容