online - javadoc wiki



返回NULL的替代方法 (10)

主要取決於場景。 如果你的應用程序本身就是這個方法的生產者和消費者,那麼它完全取決於你決定做什麼,否則你需要根據方法的使用和客戶端的需求來決定。

https://src-bin.com

   /**
     * Returns the foo with the matching id in this list
     * 
     * @param id the id of the foo to return
     * @return the foo with the matching id in this list
     */
    public Foo getFoo(int id)
    {
        for (Foo foo : list)
        {
            if (foo.getID() == id)
            {
                return foo;
            }
        }

        return null;
    }

如果沒有找到foo而不是返回null ,我應該throw exception嗎? 這是否重要,在這個問題上是否有“最佳實踐”成語? 順便說一句,我知道我的例子有點做作,但是我希望你能明白...

謝謝。

編輯

更改代碼以獲取基於id的 Foo ,以更好地展示真實世界的場景。


Answer #1

另一個觀點我沒有在其他答案中讀到以下內容:

list中是否包含Foo null ? 如果是這種情況,則不知道該id是否被找到,或者是否與null關聯。 在這種情況下:

  • 拋出列表未找到的異常;
  • 將結果封裝在另一個對像中(例如SearchResult ,它告訴你是否找到了對象,它是關聯的id,結果是否定的,否則沒有結果)。
  • 創建方法existsFoo(int id)

每個解決方案都有自己的問題,這取決於使用的​​情況:

  • 正如其他人所指出的, Exception例外的 ;
  • 每次您想要重新搜索時,都必須分配一個包裝SearchResult 。 包裝可以變化,但這會帶來很多新的困難和問題。
  • existsFoo必須搜索使得知道密鑰是否存在的成本翻倍的列表。

一般我可以說:

  • 身份證是不是被發現異常? 使用IllegalArgumentException ;
  • 結果傳遞給其他類,用作對象嗎? 使用包裝,例如SearchResult ;
  • getFoo只檢查是否為空(它是否存在)? 使用另一種方​​法existsFoo

Answer #2

如果可以的話,最好避免例外,但有時你不能。 在這種情況下,如果你在列表中存儲了null呢? 你不能區分'找到空'和'找不到你想要的'之間的區別。

有一個模式,它被稱為選項類型 ,它在Scala中使用了很多。 你要么返回一個容器的物品,要么是一個容器裡寫著“我是空的”。 維基文章將會給出更好的圖片。

你也可以有一個“這是否存在於收藏? 方法返回一個bool,然後從上面的代碼中拋出一個異常,如果你沒有先檢查。

而只是一個評論完全無關你的實際問題。 如果你實現了equals,那麼只有在兩個對象實際上被認為是相等的時候它才會返回true。 因此,上面的代碼必須總是返回你傳入的對象!


Answer #3

如果記錄為有效結果,則返回null是很好的。

另一個選項是空對像模式。 那就是 - Foo一個沒有任何數據的實例:

public class Foo {
    public static final Foo NULL_FOO = new Foo();
}

並返回它。


Answer #4

我會說這取決於你的應用程序,以及如何使用該方法。

  1. 如果您期望“未找到”結果頻繁發生,可能會對性能產生負面影響*,則返回null,然後在調用者中檢查它。
  2. 如果“找不到”的結果會比較少見,或者會導致你的應用放棄請求,那麼拋出異常就沒事了。 例外可以使你的代碼更容易閱讀,因為你可以保證成功的返回會產生一個對象,所以你不必對它進行空值檢查。

我同意這種意見,即異常應該用於超出錯誤條件的特殊條件。 我也採用了Spring / Hibernate對非檢查異常的偏好,避免了繁瑣的try / catch邏輯。

*使用異常與返回null沒有太大的性能開銷。 我只是做了一個快速測試,調用一個方法一百萬次返回null,而另外一個方法只有535ms則拋出異常。


Answer #5

我會說這取決於你的方法的語義。

將幾乎總是在列表中找到? (例如,如果它是一個擁有有限數量對象的緩存)。 如果是這樣,那麼找不到可能意味著出了什麼問題 - 例如一些應用程序初始化失敗,或者密鑰無效 - 並且異常可能是合理的。

但是,在大多數情況下,我會返回null 。 也許客戶知道對象可能不在那裡,並且已經編碼邏輯來處理這種情況; 如果你使用了一個例外,那麼這個代碼就會難於閱讀,理解和維護。

一些API實際上提供了兩個方法:一個可能返回null的find方法和一個拋出異常的getload方法。

嗯,如果有疑問,可以贊成空:)


Answer #6

最好的方法就是在Javadoc中說,當沒有找到匹配時,返回null

另一種方法可能是返回可能為空的匹配列​​表(可能有多個)。但是我不喜歡這種方法。

另一種方法可能是返回一個Foo類型的NULL_FOO值。

我寧願只是返回null。

解決這個問題的一個方法就是看看你將要做什麼,並且豐富這個函數,以便返回的值在方法中被使用,而不是被返回。 例如,如果你打算用這個值調用一個方法,只需要在函數中調用它來避免返回任何東西。


Answer #7

返回null不僅更簡單,而且表現也更好。 必須使用例外來處理特殊情況。


Answer #8

這可能不會直接回答你的問題,但它來自我從類似主題的成員獲得的一些評論。

如果沒有找到foo,而不是返回null,我應該拋出異常嗎? 這是否重要,在這個問題上是否有“最佳實踐”成語? 順便說一句,我知道我的例子有點做作,但是我希望你能明白...“

從我收集的內容來看,異常應該從方法拋出,異常涉及給方法的參數。 例如,接受File實例的方法將拋出一個NullPointerException或一個IOException。 這是因為調用者和被調用者之間有一個合同,即調用者應該發送有效的對象,並在他們無效的情況下照顧他們。

另外,您需要決定是否處理前置和後置條件。 你可以在一個方法的開始處放置一個守衛來處理參數,這樣可以節省很多代碼。 然而,有些人認為這是一個不正確的方法,因為應該事先在UI中進行驗證。

最後,如果意圖檢索單個實例,則返回空對像是完全有效的。 這是為了解釋一個對像沒有被找到或不存在。 說到對象組,我認為這個約定就是返回一個空的Collection / List。


Answer #9

這是一個老問題,但是我沒有找到這裡提到的guava的Optional類,也沒有找到JDK的Optional (來自Java 8),它提供相同的功能和更多的功能。

這篇文章是一個很好的概述使用番石榴的選擇的原因。 我強烈推薦閱讀。

這是一個摘錄:

重點是什麼?

除了賦予null一個名字所帶來的可讀性的增加外,Optional的最大優點是它的防白痴。 如果你想要你的程序編譯的話,它會迫使你主動思考這個缺失的情況,因為你必須主動打開Optional並處理這個問題。 Null使得簡單地忘記事情變得非常容易,雖然FindBugs有幫助,但是我們不認​​為它解決了這個問題。

當您返回可能或不可能“存在”的值時,這一點尤其重要。 您(和其他人)更有可能忘記other.method(a,b)可能會返回空值,而您可能會忘記在執行other.method時可能為null。 返回Optional使得調用者不可能忘記這種情況,因為他們必須自己拆開對象來編譯代碼。

我個人的看法是,如果這很重要的話,返回null在像Java這樣已經冗長的語言中並不是那麼糟糕。 該方法的簽名有時尖叫,可能有某種空類型的結果,並使用可選不會添加任何語義方面無論如何。 例如:

public Point2D intersect(Line line)

或者在按鍵查找地圖中的值的方法中。

如果有人調用這樣的方法,並對結果執行空檢查,那很明顯是怎麼回事(檢查平行線或沒有找到的鍵)。 我會贊成返回null,以免我膨脹我的代碼。

但是我總是將它記錄在javadoc中。





return-value