[英]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;
}
我是否需要在hashCode
和equals
函數中使用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)
我認為如果對象處於錯誤的狀態,我可以提前發現錯誤而不是返回零...
我會親自檢查無效並使方法總是返回,沒有例外。
雖然運行時異常通常沒有記錄,並且可以拋到任何地方,但我認為通過equals
和hashCode
拋出它們通常很差。 一方面,我完全可以看到你在完全填充之前被放入地圖的觀點...但另一方面,很難真正知道將在何處調用equals
。
正如lc在評論中所說的那樣,如果你真的想拋出一個異常,那么拋出一個IllegalStateException
就可以更清楚地說明這是故意的,而不是讓“默認情況下”拋出NullReferenceException
,這會讓它看起來像你只是沒有想到空場景。
一般來說,答案是“它取決於”。
如果你永遠不應該看到該類的實例為null
,那么允許拋出NPE是合理的。 NPE表示一個錯誤; 即你的非正式不變量被打破的情況。
如果在某些情況下可以合理地預期具有null
的實例,那么您應該處理null
情況而不拋出異常。
在這種特殊情況下,您顯然正在處理如果對象尚未持久化,則id
字段可以為null的對象。 這提出了一個棘手的問題:
如果不允許id
為null
,則必須注意不要將非持久對象放入哈希表中。
如果你確實允許id
為null
,那么你就會遇到這樣的問題,即如果你將一個對象添加到一個哈希表中,然后它就會持久存在,那么hashcode
可能會改變,從而導致哈希表的破壞。 所以,現在你需要通過在瞬態字段中記憶對象的哈希碼值來防御這種情況。 並且大致相同的問題出現在equals
。 如果在持久化對象時更改了相等性,那么最好不要在同一個哈希表中混合使用持久密鑰和非持久密鑰。
考慮到所有這些,我建議要么拋出NPE,要么不使用equals
/ hashcode
的id
字段。
為了驗證對象的狀態,您應該使用Bean驗證框架來確保對象的狀態是有效的。
沒有 hashcode和equals方法不應該拋出異常。
equals
方法必須檢查無效。 當創建對象時,創建者有責任確保對象處於有效狀態,因此hashCode
永遠不會拋出異常。 對於那個bean,可以使用驗證。 IMO。
更新 :當您使用為您創建bean的bean框架時,您必須依賴bean驗證。 但是否則它必須是Factory
的責任,它創建對象以確保只創建一個有效的實例 。
您永遠不希望代碼中出現空指針異常。 從不 。 特別是在您自己的代碼之外大量使用的函數中。 hashcode
equals
toString
永遠不應該拋出異常。
順便說一句:你總是可以將id作為哈希碼返回。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.