我使用Java 8編碼已經有些年頭,既用於新的應用程序,也用來遷移現有的應用,感受是時候寫一些我發現的很是有用的「最佳實踐」。程序員
我我的並不喜歡「最佳實踐」這個說法,由於它意味着「一刀切」的解決方案,而編碼不多是這樣的工做方式——咱們須要親自去發現什麼樣的解決方案纔是有效的。編程
可是我發現了一些Java 8代碼中能夠幫助咱們的一些選擇,讓咱們一塊兒來看看吧。數組
1.Optional架構
Optional是一個嚴重被低估的功能,而且有潛力刪除不少困擾咱們的NullPointerExceptions。這在代碼邊界中(要麼是正在使用的API,要麼是正在暴露的API)特別有用,由於它容許你和你的調用代碼來推理所期待的東西。函數
然而,不加思考和設計就應用Optional可能會致使影響大量的類,並可能致使可讀性更差。下面是一些關於如何高效使用Optional的技巧。性能
Optional應該只用於返回類型學習
……不是參數,也不是字段。幸運的是,IntelliJ IDEA的讓你打開檢查來查看是是否遵循這些建議。測試
Optional值應在遇到它們的地方中處理。IntelliJ IDEA的建議會防止代碼Optional泄漏,因此請記得在你發現Optional的地方處理它,迅速採起行動。編碼
不該該簡單調用get()設計
Optional的功能是表達這個值多是空的,並讓你應對這種狀況。所以,在對它作任何事情以前必定要檢查是否有一個值。只是簡單得調用get()而不先檢查isPresent()在某些時候可能會致使空指針。幸運的是,IntelliJ IDEA也有檢查能夠提醒你這一點。
可能有更優雅的方式
結合了get()的isPresent()固然會很贊…
……但也有更優雅的解決方案。你可使用orElse在萬一是空值的狀況下給一個替代方案。
……或者你可使用orElseGet說明在值爲空的狀況下調用哪一個方法。這彷佛與上面的例子相同,但supplier方法將只在須要的時候調用,所以,若是這是一種昂貴的方法,那麼使用lambda會有更佳性能。推薦閱讀:JDK8新特性之Stream流。
2.使用Lambda表達式
Lambda表達式是Java 8的主要特色之一。即便你尚未使用Java 8,你如今可能已經對它們有了基本的瞭解。它們是用Java編程的一種新的方式,而且什麼是「最佳實踐」還不明顯。下面是我喜歡遵循的一些指引。
保持簡短
函數式程序員與較長的lambda表達式相處會更愉快,但那些淫浸於Java多年的人會發現保持lambda表達式爲區區幾行代碼更容易。你甚至可能更願意將其限制到一行代碼,而且你能夠輕鬆重構較長的表達式爲一個方法。
這些甚至可能會成爲方法引用。方法引用一開始會以爲有點陌生,但實際上堅持方法引用是有價值的,由於它們在某些狀況下有助於可讀性,後面我會討論到這一點。
明確
類型信息缺乏lambda表達式,因此你可能會以爲包含類型信息用於參數會頗有用。
正如你所見,這回變得至關笨拙。因此我更喜歡給參數取一個有用的名字。固然,無論你有沒有這麼作,IntelliJ IDEA可讓你看到參數得類型信息。
甚至是lambda所表明的函數式接口:
3.針對Lambda表達式設計
我認爲lambda表達式有點像泛型——和泛型一塊兒,咱們常用它們(例如,添加類型信息到List< >),但最好咱們能夠設計一種方法或一個具備泛型類型(例如Person< T >)的類。
一樣的,當使用相似於Streams API的東西時,咱們會傳遞lambda表達式,但更好的是創造一個須要lambda參數的方法。推薦閱讀:JDK8新特性之Lambda表達式。
可是,若是你發現本身處於這類狀況下,下面有一些超棒的技巧。
IntelliJ IDEA能夠幫你引進函數式參數
這讓你能夠在有人將傳遞一個lambda而非Object的地方建立一個參數。此功能的好處是,它代表,現有函數式接口匹配規格說明。
這會致使…
使用現有的函數式接口
隨着開發人員愈來愈熟悉Java 8代碼,咱們就能知道當使用如Supplier和 Consumer的接口時,會發生什麼,以及建立一個本地的ErrorMessageCreator(舉個例子)可能會形成混亂,並且浪費。看看這個函數包瞭解一下哪些已是可用的。推薦閱讀:JDK8新特性之函數式接口。
添加@FunctionalInterface到函數式接口
若是你確實須要建立本身的函數式接口,那麼就這樣用此註釋標記。這彷佛沒有太大的做用,但IntelliJ IDEA會告訴你,在你的接口不能匹配用於函數式接口的異常的時候。當你沒有指定要覆蓋的方法時,它會標誌:
當你指定了太多方法的時候,它會標誌:
而且若是你應用它到一個類而不是接口時,它會警告你:
lambda表達式可用於帶有一個單一抽象方法的任何接口,但它們不能用於符合相同標準的抽象類。彷佛不合邏輯,但就是這樣。
4.Stream
Stream API是Java 8另外一個大特色,而且我認爲咱們還真的不知道這對咱們的編碼方式會產生多大的改變。下面是我發現的一些有用的東西
排隊點操做符
我我的更喜歡排隊個人流操做。固然,你沒有必要這樣,當我發現這樣作對我有幫助:
此外,在我看來,它更整潔。若是咱們按照這個模式,在減小代碼行數方面咱們並無增長不少。
你可能須要調整格式設置以排列點操做符。
使用方法引用
是的,確實須要一段時間來適應這個奇怪的語法。可是,若是使用得當,它確實能夠增長可讀性。請看:
與(相對)新的Objects類上的輔助方法相比較:
後者的代碼對於哪些值是要保存的更加明確。當lambda能夠被摺疊到方法參考的時候,IntelliJ IDEA一般會讓你知道。
當遍歷一個集合時,在可行的狀況下使用Streams API
…或者新的集合方法,如forEach。IntelliJ IDEA給你建議是:
通常使用Streams API比循環和if語句的組合更加明確。例如:
IntelliJ IDEA建議這可重構爲:
我所作的性能測試代表這種重構使人驚訝——並不老是可預測性能是保持不變,改善仍是變得更糟。與往常同樣,若是性能在應用程序中是關鍵,那麼在交付一種風格到另外一種以前衡量它。
遍歷數組時使用循環
可是,使用Java 8並不必定意味着你必須處處使用流和新的集合方法。IntelliJ IDEA會建議轉換成流,可是,這並不意味着你必須回答「yes」(記得檢查是能夠抑制或關閉的)。
特別是,遍歷原始類型的小型數組幾乎確定會用,以得到更好的性能循環,極可能(至少對於Java開發人員是新的流)更具可讀性。
與任何技巧同樣,規則並非一成不變的,但你應該決定是儘量地使用Streams API,仍是依然對一些操做使用循環。總之,要一致。
感興趣的能夠本身來個人Java架構羣,能夠獲取免費的學習資料,羣號:855801563 對Java技術,架構技術感興趣的同窗,歡迎加羣,一塊兒學習,相互討論。