問題:在Java里重寫equals和hashCode要注意什么問題
重寫equals和hashCode有哪些問題或者陷阱需要注意?
回答一
理論(對于語言律師或比較傾向于數學的人):
equals() (javadoc) 必須定義為一個相等關系(它必須是自發的,對稱的并且是傳遞的),另外它一定是一致的(如果一個對象沒有被修改,那么它一定返回相同的值)。而且 o.equals(null)一定要返回false
hashCode() (javadoc)一定要是一致的(如果一個對象沒有按照equals修改的話,它一定保證返回一個相同的值)
這兩個方法的關系是:
無論如何 a.equals(b),那么a.hashCode() 必須等于b.hashCode().
實際上:
如果你重寫了其他一個,那么你必須要重寫另外那個
使用計算equals()的一組相同字段去計算hashcode()
使用來自于Apache Commons Lang library的優秀工具類 EqualsBuilder and HashCodeBuilder
例如
public class Person {private String name;private int age;// ...@Overridepublic int hashCode() {return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers// if deriving: appendSuper(super.hashCode()).append(name).append(age).toHashCode();}@Overridepublic boolean equals(Object obj) {if (!(obj instanceof Person))return false;if (obj == this)return true;Person rhs = (Person) obj;return new EqualsBuilder().// if deriving: appendSuper(super.equals(obj)).append(name, rhs.name).append(age, rhs.age).isEquals();}
}
同時也要記住:
當你使用基于哈希的集合或者Map的時候例如:HashSet, LinkedHashSet, HashMap, Hashtable, or WeakHashMap,確定你放進去集合的key對象的hashcode()的值,在被放進去了集合以后就不再改變。確保這一點的可靠方法就是你的key保證不變,這也會帶來其他好處的
文章翻譯自Stack Overflow:https://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java