Effective Java 第三版——43.方法引用優於lambda表達式

Tips
《Effective Java, Third Edition》一書英文版已經出版,這本書的第二版想必不少人都讀過,號稱Java四大名著之一,不過第二版2009年出版,到如今已經將近8年的時間,但隨着Java 6,7,8,甚至9的發佈,Java語言發生了深入的變化。
在這裏第一時間翻譯成中文版。供你們學習分享之用。編程

Effective Java, Third Edition

43.方法引用優於lambda表達式

lambda優於匿名類的主要優勢是它更簡潔。Java提供了一種生成函數對象的方法,比lambda還要簡潔,那就是:方法引用( method references)。下面是一段程序代碼片斷,它維護一個從任意鍵到整數值的映射。若是將該值解釋爲鍵的實例個數,則該程序是一個多重集合的實現。該代碼的功能是,根據鍵找到整數值,而後在此基礎上加1:數組

map.merge(key, 1, (count, incr) -> count + incr);

請注意,此代碼使用merge方法,該方法已添加到Java 8中的Map接口中。若是沒有給定鍵的映射,則該方法只是插入給定值; 若是映射已經存在,則合併給定函數應用於當前值和給定值,並用結果覆蓋當前值。 此代碼表示merge方法的典型用例。ide

代碼很好讀,但仍然有一些樣板的味道。 參數count和incr不會增長太多價值,而且佔用至關大的空間。 真的,全部的lambda都告訴你函數返回兩個參數的和。 從Java 8開始,Integer類(和全部其餘包裝數字基本類型)提供了一個靜態方法總和,和它徹底相同。 咱們能夠簡單地傳遞一個對這個方法的引用,並以較少的視覺混亂獲得相同的結果:函數

map.merge(key, 1, Integer::sum);

方法的參數越多,你能夠經過方法引用消除更多的樣板。 然而,在一些lambda中,選擇的參數名稱提供了有用的文檔,使得lambda比方法引用更具可讀性和可維護性,即便lambda看起來更長。學習

對於一個方法引用,你無能爲力,由於你不能對lambda執行任何操做(只有一個難懂的異常 - 若是你好奇的話,參見JLS,9.9-2)。 也就是說,方法引用一般會致使更短,更清晰的代碼。 若是lambda變得太長或太複雜,它們也會給你一個結果:你能夠從lambda中提取代碼到一個新的方法中,並用對該方法的引用代替lambda。 你能夠給這個方法一個好名字,並把它文檔記錄下來。翻譯

若是你使用IDE編程,它將提供替換lambda的方法,並在任何地方使用方法引用。一般狀況下,你應該接受這個提議。偶爾,lambda會比方法引用更簡潔。這種狀況常常發生在方法與lambda相同的類中。例如,考慮這段代碼,它被假定出如今一個名爲GoshThisClassNameIsHumongous的類中:code

service.execute(GoshThisClassNameIsHumongous::action);

這個lambda相似於等價於下面的代碼:對象

service.execute(() -> action());

使用方法引用的代碼段既不比使用lambda的代碼片斷更短也不清晰,因此更喜歡後者。 在相似的代碼行中,Function接口提供了一個通用的靜態工廠方法來返回標識函數Function.identity()。 它一般更短,更清潔,而不使用這種方法,而是使用等效的lambda內聯代碼:x - > xblog

許多方法引用是指靜態方法,但有四種方法沒有。 其中兩個是特定(bound)和任意(unbound)對象方法引用。 在特定對象引用中,接收對象在方法引用中指定。 特定對象引用在本質上與靜態引用相似:函數對象與引用的方法具備相同的參數。 在任意對象引用中,接收對象在應用函數對象時經過方法的聲明參數以前的附加參數指定。 任意對象引用一般用做流管道(pipelines)中的映射和過濾方法(條目 45)。 最後,對於類和數組,有兩種構造方法引用。 構造方法引用用做工廠對象。 下表總結了全部五種方法引用:接口

方法引用類型 舉例 等同的Lambda
Static Integer::parseInt str -> Integer.parseInt(str)
Bound Instant.now()::isAfter Instant then = Instant.now(); t -> then.isAfter(t)
Unbound String::toLowerCase str -> str.toLowerCase()
Class Constructor TreeMap<K,V>::new () -> new TreeMap<K,V>
Array Constructor int[]::new len -> new int[len]

總之,方法引用一般爲lambda提供一個更簡潔的選擇。 若是方法引用看起來更簡短更清晰,請使用它們;不然,仍是堅持lambda

相關文章
相關標籤/搜索