Java 8:遠離萬惡之 null
Java 8 推出 3 年多了,但直到這周我才知道什麼是 Optional ……
Java 程序員經常會碰到一個讓人心煩的錯誤 : NullPointerException
尤其是和別人合作時,像我一樣的 Java 小白經常會糾結調用的方法會不會有 null value。
如果不去檢查,程序很可能運行到一半因為返回 null 而報錯閃退,對用戶的體驗帶來極大影響。如果對於每個返回值都去檢查,程序看起來會特別的難過……
舉個例子
假設我們這個周末要開一個盛大的 party,要準備的東西很多,包括必不可少的一長串酒單需要購買。組織者里正好有一位 Java 程序員,他很熱心,表示願意幫大家分擔些負擔,於是寫了一個自動準備宴會的系統。
代碼很簡單,用了 Drink,Store,DrinkOrder 三個 class 來輔助買酒的任務執行。
Drink 和 DrinkOrder 用來存要買的酒的信息。
Store class 有兩個方法:
int getDrinkPrice(String drinkName) : 根據輸入的 Drink 名稱,查看商店裡對應酒的價錢,如果該商品不存在,返回 -1。
void order(String drinkName, String drinkQuantity) : 根據輸入 Drink 的名稱和數量,自動下單。
主程序 PreparationSystem 存儲了一個所有 Store 的列表,還有三個方法:
List generateDrinkOrder() : 輔助邏輯,生成一個固定的酒單
Store findCheapestStore(String drinkName) : 輔助邏輯,根據輸入 Drink 的名稱,從已有的 Store 列表中,找到賣這種酒最便宜的商店
void prepareParty() : 主要邏輯,生成酒單,並根據酒單,花最少的價錢去買酒
這樣寫出來的代碼乍一看沒有什麼問題,但是如果生成的固定酒單中有一款非常不常見的酒 (比如說 Xtabentún ),導致 findCheapestStore 因為列表中所有的商店都沒有這種酒而返回 null,這樣程序執行到 「store.order」 的時候就會拋出 NullPointerException 的異常。
簡單的做法是在 prepareParty 里加一層對 null 值的檢測:
但這樣寫代碼寫多了滿屏都是 null,很不好維護。另外,對於什麼樣的方法要進行不為 null 的檢查也沒有足夠明確的說明。
解決方法一般有兩個,一個是加 @NotNull 的注釋 (感興趣的小夥伴自行上網查),另一個在 Java 8 中可以用的是 java.util.Optional
官方 API 對 Optional 的聲明 :
A container object which may or may not contain a non-null value. If a value is present, isPresent() will return true and get() will return the value.
因為是一個容器類型,所以想用 Optional 的話,只需要很簡單地將 findCheapestStore 的返回值從 Store 改為 Optional ,並且把返回的 cheapestStore 用 Optional 的靜態方法包裝一下就好。
更改之後的代碼如下:
相應的,prepareParty 的 for loop 就不需要對 null 值進行檢測:
如果真的有人在看代碼的話,你會說 「 誒,這tm不和直接 check null 一樣嗎,只不過把 != null 改成了 isPresent() 」。
你講的很有道理,這麼寫確實就沒有區別了,反而使代碼更加複雜,所以推薦的是用 Optional 里的 ifPresent 方法。
用 lambda 表達式改寫後的 for loop :
是不是比總去檢查 null 更簡潔易懂好維護了呢?
吐槽一下 : 微信公眾號改代碼格式太困難了……
原創開通了就不放二維碼求關注了,不過安卓的小夥伴應該能看到點不同的東西 ( 手動滑稽 )。
※憑什麼女追男就沒有好下場?
※不要老拿自己是「女人」說事兒
※期待Star Rose的綻放
※返樸:我把憂傷塵封在盒子里
※婚姻最怕宮星同位
TAG:公眾號 |