簡體   English   中英

在Java中允許和接受hashCode和equals方法中的異常嗎?

[英]Are exceptions in hashCode and equals methods allowed and acceptable in Java?

一些類由框架填充(如bean)。 因此,您無法保證所有字段都已設置。

例如:標記為@Entity類通常具有Integer id字段。 hashCode可以寫成:

public int hashCode() {
    return id.hashCode();
}

但是defencive代碼可能看起來像:

public int hashCode() {
    return (id != null) ? id.hashCode() : 0;
}

我是否需要在hashCodeequals函數中使用try { ... } catch (Exception e)對null或環繞代碼進行寫檢查?

我沒有關於defencive編碼的論據就是這種情況,因為它隱藏了將不一致的對象隱藏到集合中並導致后期錯誤。 我錯了嗎?

更新我寫了這樣的代碼:

import java.util.*;

class ExceptionInHashcode {

    String name;

    ExceptionInHashcode() { }
    ExceptionInHashcode(String name) { this.name = name; }

    public int hashCode() {
        // throw new IllegalStateException("xxx");
        return this.name.hashCode();
    }

    public static void main(String args[]) {
        Hashtable list = new Hashtable();
        list.put(new ExceptionInHashcode("ok"), 1);
        list.put(new ExceptionInHashcode(), 2); // fail
        System.out.println("list.size(): " + list.size());
    }
}

並運行它:

java -classpath . ExceptionInHashcode
Exception in thread "main" java.lang.NullPointerException
        at ExceptionInHashcode.hashCode(ExceptionInHashcode.java:12)
        at java.util.Hashtable.hash(Hashtable.java:262)
        at java.util.Hashtable.put(Hashtable.java:547)
        at ExceptionInHashcode.main(ExceptionInHashcode.java:18)

我認為如果對象處於錯誤的狀態,我可以提前發現錯誤而不是返回零...

我會親自檢查無效並使方法總是返回,沒有例外。

雖然運行時異常通常沒有記錄,並且可以拋到任何地方,但我認為通過equalshashCode拋出它們通常很差。 一方面,我完全可以看到你在完全填充之前被放入地圖的觀點...但另一方面,很難真正知道將在何處調用equals

正如lc在評論中所說的那樣,如果你真的想拋出一個異常,那么拋出一個IllegalStateException就可以更清楚地說明這是故意的,而不是讓“默認情況下”拋出NullReferenceException ,這會讓它看起來像你只是沒有想到空場景。

一般來說,答案是“它取決於”。

  • 如果你永遠不應該看到該類的實例為null ,那么允許拋出NPE是合理的。 NPE表示一個錯誤; 即你的非正式不變量被打破的情況。

  • 如果在某些情況下可以合理地預期具有null的實例,那么您應該處理null情況而不拋出異常。


在這種特殊情況下,您顯然正在處理如果對象尚未持久化,則id字段可以為null的對象。 這提出了一個棘手的問題:

  • 如果不允許idnull ,則必須注意不要將非持久對象放入哈希表中。

  • 如果你確實允許idnull ,那么你就會遇到這樣的問題,即如果你將一個對象添加到一個哈希表中,然后它就會持久存在,那么hashcode可能會改變,從而導致哈希表的破壞。 所以,現在你需要通過在瞬態字段中記憶對象的哈希碼值來防御這種情況。 並且大致相同的問題出現在equals 如果在持久化對象時更改了相等性,那么最好不要在同一個哈希表中混合使用持久密鑰和非持久密鑰。

考慮到所有這些,我建議要么拋出NPE,要么不使用equals / hashcodeid字段。

為了驗證對象的狀態,您應該使用Bean驗證框架來確保對象的狀態是有效的。

沒有 hashcode和equals方法不應該拋出異常。

equals方法必須檢查無效。 當創建對象時,創建者有責任確保對象處於有效狀態,因此hashCode永遠不會拋出異常。 對於那個bean,可以使用驗證。 IMO。

更新 :當您使用為您創建bean的bean框架時,您必須依賴bean驗證。 但是否則它必須是Factory的責任,它創建對象以確保只創建一個有效的實例

您永遠不希望代碼中出現空指針異常。 從不 特別是在您自己的代碼之外大量使用的函數中。 hashcode equals toString永遠不應該拋出異常。

順便說一句:你總是可以將id作為哈希碼返回。

暫無
暫無

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

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