??lambda比匿名類的首要優(yōu)勢是它們更簡潔憨降。Java提供了一個方式來生成函數(shù)式對象比lambda更簡潔“:方法引用。下面是一個程序的代碼片段该酗,該程序維護(hù)從任意鍵到整數(shù)值的映射授药。如果該值被解釋為鍵實(shí)例數(shù)的計(jì)數(shù),則該程序是一個多集實(shí)現(xiàn)呜魄。代碼段的功能是:如果數(shù)字1不在映射中悔叽,則將其與鍵關(guān)聯(lián);如果鍵已經(jīng)存在,則增加關(guān)聯(lián)值:
map.merge(key, 1, (count, incr) -> count + incr);
??注意到這個代碼使用merge方法爵嗅,在Java8中被添加到Map接口娇澎。如果給出的鍵沒有映射,方法僅僅會插入給予的值睹晒;如果已經(jīng)存在映射趟庄,merge將給定函數(shù)應(yīng)用于當(dāng)前值和給定值,并使用結(jié)果覆蓋當(dāng)前值伪很。這段代碼代表了merge方法的一個典型用例戚啥。
??代碼讀起來很好,但是仍然有一些樣板文件锉试。參數(shù)count和incr沒有增加多少值猫十,而且它們占用了相當(dāng)大的空間。實(shí)際上,lambda告訴你的只是函數(shù)返回它兩個參數(shù)的和拖云。從Java8開始贷笛,Integer(以及所有其他裝箱數(shù)值原生類型)提供了一個靜態(tài)方法sum,也是做了同樣的事情宙项。我們可以簡單地向這個方法傳遞一個引用并以更少的視覺混亂獲得相同的結(jié)果:
map.merge(key, 1, Integer::sum);
??方法的參數(shù)越多昨忆,您可以通過方法引用消除的樣板文件就越多。然而杉允,在一些lambda中邑贴,你選擇的參數(shù)名提供了有用的文檔,使得lambda比方法引用更具有可讀性叔磷,即使lambda更長拢驾。
??你不能對方法引用做任何你不能對lambda做的事情(有一個不太明顯的例外—如果您好奇,請參閱JLS, 9.9-2)改基。也就是說繁疤,方法引用經(jīng)常導(dǎo)致更短,更清晰的代碼秕狰。它們也能提供你一個輸出如果lambda太長或太復(fù)雜:你可以從lambda中提取代碼為一個新的方法并用方法引用替代lambda稠腊。您可以給該方法起一個好名字,并將其文檔化到您的核心內(nèi)容鸣哀。
??如果你使用IDE編程架忌,只要它可以,它會提供你用方法引用替代lambda的功能我衬。你應(yīng)該經(jīng)常叹放,但不要總要,接受IDE的建議挠羔。有時(shí)候井仰,lambda將比方法引用更簡潔。當(dāng)方法在同一個類中會經(jīng)常發(fā)生破加。比如俱恶,考慮這個片段,假設(shè)發(fā)生在一個名為GoshThisClassNameIsHumongous的類中:
service.execute(GoshThisClassNameIsHumongous::action);
??等價(jià)的lambda長這個樣子:
service.execute(() -> action());
??該片段使用方法引用并不比lambda更短或更清晰范舀,所以建議使用后者合是。類似的,F(xiàn)unction接口提供了一個泛型靜態(tài)工廠方法返回它本身的方法尿背,F(xiàn)unction.identity()端仰。很明顯不用這個方法會更短,相對的lambda是 x->x田藐。
??許多方法引用引用了靜態(tài)方法荔烧,但是有四種不是這樣的吱七。其中兩種是 bound和 bound實(shí)例方法引用。在綁定引用中鹤竭,接收對象在方法引用中指定踊餐。綁定引用在本質(zhì)上類似于靜態(tài)引用:函數(shù)對象接受與引用方法相同的參數(shù).在未綁定引用中,當(dāng)應(yīng)用函數(shù)對象時(shí)臀稚,通過方法聲明參數(shù)之前的附加參數(shù)指定接收對象.未綁定引用通常用作流管道中的映射和篩選函數(shù)( item45 ).最后吝岭,有兩種 構(gòu)造方法引用。為類和數(shù)組使用吧寺。構(gòu)造方法引用作為工廠對象窜管。五種方法參考文獻(xiàn)匯總?cè)缦卤?
??總之,方法引用通常提供比lambdas更簡潔的替代方法稚机。 當(dāng)方法引用比它們更短更清晰的時(shí)候幕帆,用它們;當(dāng)它們不是赖条,堅(jiān)持lambda失乾。
本文寫于2019.7.12,歷時(shí)1天