簡體   English   中英

為什么 java.util.Map.containsKey 會為不支持空鍵的映射拋出空指針異常?

[英]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 的等價物將對其具有相等約束,並且對所有可以通過相等進行比較的值都有效。

Object.equalsjava 文檔

對於任何非空引用值 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) 檢查以及為什么它們會拋出異常,我認為這是因為設計,並且有充分的理由,明確給出輸出出了什么問題。

注意:

  1. 您的密鑰可以是已定義密鑰類型的子類型,因此,可能需要對其進行強制轉換。 由於它是內部轉換的,因此運行時不知道您將提供什么作為參數。 因此,最好拋出這個;
  2. 您的密鑰可能是明確的,也可能是在幕后的某個地方(例如,在多線程場景中), get null ,這也是處理此場景的原因。

請注意,這兩個異常都被定義為可選異常,因此,再次強調,實現應該拋出它們並不是必須的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM