![](/img/trans.png)
[英]Does java.util.HashMap.containsKey(Object key) implementation violate java.util.Map.containsKey(Object key) documentation?
[英]Why does java.util.Map.containsKey throw a null pointer exception for maps which don't support null keys?
Java 文檔是這樣說的:
拋出:
ClassCastException - 如果該鍵的類型不適合此映射(可選)
NullPointerException - 如果指定的鍵為空並且此映射不允許空鍵(可選)
我相信這個決定有一個很好的理由,但我不知道它到底是什么。 即使映射不允許空值作為鍵,containsKey 也不應該總是返回 false 嗎? 如果地圖不允許鍵,則 Null 顯然不是地圖中的鍵,所以我認為它應該返回 false。
我想到的特定實例是 TreeMap。 出於性能原因,我將 Map 實例從 HashMap 更改為 TreeMap,這導致了一個微妙的錯誤,因為 HashMap 的 containsKey 不會引發空指針異常。 我覺得這種類型的更改沒有充分的理由導致像這樣的微妙錯誤。
編輯我知道 NullPointerException 的(可選)性質。 在我看來,它的可選性質並不能解釋為什么允許它
為了說明為什么我對此感到困惑,containsKey 本質上是通過相等來比較鍵。 在某種程度上,我來自函數式背景,其中(比如 Haskell)containsKey 的等價物將對其具有相等約束,並且對所有可以通過相等進行比較的值都有效。
對於任何非空引用值 x,x.equals(null) 應返回 false。
因此,我認為如果映射不支持空鍵,則 containsKey 必須返回 false,因為實現“應該”等效於使用 k.equals(input) 迭代鍵。
我相信這是一個設計決定。
有兩種可能的情況:
1.您在支持空鍵的地圖上使用 containsKey。 作為此函數的用戶,您希望得到 true 或 false。 絕對沒有理由返回 nullPointerException,因為我們將 'null' 視為任何其他鍵,所以就像您期望 'someKey' 不存在時返回 false 一樣,對於 null 也是如此。
2.您在不支持空鍵的地圖上使用 containsKey。 返回 false 將是一個奇怪的決定,因為它不是一個可能的鍵。 此外,用戶可能有對他試圖用作鍵的某個對象的引用。 用戶更願意得到一個 NullPointerException 異常,所以他會意識到這種情況,試圖獲取/設置一個空對象作為鍵。
您的論點平均適用於ClassCastException
:即使映射不允許該類型的值作為鍵,也不應該containsKey
總是返回 false 嗎?
回答:API(記錄的行為)不是強制實現檢查給定鍵的有效性,而是允許針對無效鍵值拋出異常。
請注意,這兩個例外都被列為“(可選)”,這意味着是否執行該操作取決於實現。 實現可以選擇簡單地返回false
,或者它可以選擇拋出這些異常之一。
實現可能會選擇不為此添加特殊邏輯,因此如果算法“本機”拋出異常,那就這樣吧。 API 被記錄為允許這種默認行為。
例如, TreeMap
將本機拋出ClassCastException
,因為在嘗試調用compare()
/ compareTo()
時會發生這種情況。 HashMap
不關心對象類型,因此永遠不會拋出ClassCastException
。
對於不支持空鍵的映射, containsKey()
的邏輯可能會或可能不會做一些事情,如果給定的鍵是空的,則拋出NullPointerException
,這是一個有效的結果,因此該邏輯不必浪費額外的代碼來處理它。
首先,在Map<K, V>
接口中聲明了containsKey(Object key)
,它沒有聲明拋出任何東西,因此它取決於實現。
如果問題是為什么實現不在內部執行所有這些 (null, cast) 檢查以及為什么它們會拋出異常,我認為這是因為設計,並且有充分的理由,明確給出輸出出了什么問題。
注意:
null
,這也是處理此場景的原因。請注意,這兩個異常都被定義為可選異常,因此,再次強調,實現應該拋出它們並不是必須的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.