??lambda比匿名類的首要優勢是它們更簡潔。Java提供了一個方式來生成函數式對象比lambda更簡潔“:方法引用。下面是一個程序的代碼片段,該程序維護從任意鍵到整數值的映射。如果該值被解釋為鍵實例數的計數,則該程序是一個多集實現。代碼段的功能是:如果數字1不在映射中,則將其與鍵關聯;如果鍵已經存在,則增加關聯值:
map.merge(key, 1, (count, incr) -> count + incr);
??注意到這個代碼使用merge方法,在Java8中被添加到Map接口。如果給出的鍵沒有映射,方法僅僅會插入給予的值;如果已經存在映射,merge將給定函數應用于當前值和給定值,并使用結果覆蓋當前值。這段代碼代表了merge方法的一個典型用例。
??代碼讀起來很好,但是仍然有一些樣板文件。參數count和incr沒有增加多少值,而且它們占用了相當大的空間。實際上,lambda告訴你的只是函數返回它兩個參數的和。從Java8開始,Integer(以及所有其他裝箱數值原生類型)提供了一個靜態方法sum,也是做了同樣的事情。我們可以簡單地向這個方法傳遞一個引用并以更少的視覺混亂獲得相同的結果:
map.merge(key, 1, Integer::sum);
??方法的參數越多,您可以通過方法引用消除的樣板文件就越多。然而,在一些lambda中,你選擇的參數名提供了有用的文檔,使得lambda比方法引用更具有可讀性,即使lambda更長。
??你不能對方法引用做任何你不能對lambda做的事情(有一個不太明顯的例外—如果您好奇,請參閱JLS, 9.9-2)。也就是說,方法引用經常導致更短,更清晰的代碼。它們也能提供你一個輸出如果lambda太長或太復雜:你可以從lambda中提取代碼為一個新的方法并用方法引用替代lambda。您可以給該方法起一個好名字,并將其文檔化到您的核心內容。
??如果你使用IDE編程,只要它可以,它會提供你用方法引用替代lambda的功能。你應該經常,但不要總要,接受IDE的建議。有時候,lambda將比方法引用更簡潔。當方法在同一個類中會經常發生。比如,考慮這個片段,假設發生在一個名為GoshThisClassNameIsHumongous的類中:
service.execute(GoshThisClassNameIsHumongous::action);
??等價的lambda長這個樣子:
service.execute(() -> action());
??該片段使用方法引用并不比lambda更短或更清晰,所以建議使用后者。類似的,Function接口提供了一個泛型靜態工廠方法返回它本身的方法,Function.identity()。很明顯不用這個方法會更短,相對的lambda是 x->x。
??許多方法引用引用了靜態方法,但是有四種不是這樣的。其中兩種是 bound和 bound實例方法引用。在綁定引用中,接收對象在方法引用中指定。綁定引用在本質上類似于靜態引用:函數對象接受與引用方法相同的參數.在未綁定引用中,當應用函數對象時,通過方法聲明參數之前的附加參數指定接收對象.未綁定引用通常用作流管道中的映射和篩選函數( item45 ).最后,有兩種 構造方法引用。為類和數組使用。構造方法引用作為工廠對象。五種方法參考文獻匯總如下表:
??總之,方法引用通常提供比lambdas更簡潔的替代方法。 當方法引用比它們更短更清晰的時候,用它們;當它們不是,堅持lambda。
本文寫于2019.7.12,歷時1天