Optional亂用Empty之No value present


前言

看到好多文章都是推薦采用Optinal的,而經常我遇到問題的時候就想:如果設計成optional的話就不會忽略這種NullPointException錯誤了。然而,optional並不是想用就隨便用的。今天花了10分鍾追蹤一個bug,根源就是optional濫用。

問題描述

API返回失敗,沒有描述原因。看着蛋疼,因為公開的API不方便返回錯誤詳情。於是查log,發現錯誤日志的message為:No value present。沒搞清楚這個錯誤信息是哪一層跑出來的。需要進一步跟蹤。A=>B=>C=>D,一直追蹤到C層才找到問題。

問題代碼如下:

public FieldBuilder withSubcategoryId(Optional<String> id) {
    this.id = id.get();
    return this;
}

這是一個創建工廠類,負責創建一個可以使用對象。所有的字段都采用了Opetional的包裹。這個是對象,理應不包含業務邏輯,應該沒有錯誤異常。如果有異常應該顯式的throws出來,不然這個非檢查性異常將在出現bug的時候難以定位。而這里確實有一個異常沒有捕獲,而且也不能保證不會發生,甚至就是這里引起的bug:java.util.Optional#get

源碼如下:

/**
 * If a value is present in this {@code Optional}, returns the value,
 * otherwise throws {@code NoSuchElementException}.
 *
 * @return the non-null value held by this {@code Optional}
 * @throws NoSuchElementException if there is no value present
 *
 * @see Optional#isPresent()
 */
public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

雖然沒有顯式的拋出異常,但在javadoc中寫清楚了會出現的問題。而我們這些新手則沒有認真看文檔就想當然的采用了。以為當內容為null的時候get出來的還是null

Find Uage找這個Builder的用法發現:

new FieldBuilder().withSubcategoryId(Optional.ofNullable(entity.getSubcategoryId()))

這里直接使用了Optional.OfNullable。然而,我們知道在下一步中會調用get,get的時候回判斷是否是nullnull會拋出異常。這簡直就是自己挖坑,寫一個條件拋異常,而傳參數又專門去符合這個條件。前面也沒有校驗,外面也沒有捕獲異常,最終導致異常直接一路拋出到API外層去了。

結論

Optional不要濫用,Optional不是安全的隨便用的,Optional用的時候記得捕獲異常。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM