This question's answers are a community effort。编辑现有答案以改善此职位。它目前不接受新的答案或互动。









覆盖equalshashCode时必须考虑哪些问题/陷阱?

最佳答案

理论(对于语言律师和数学倾向者):

equals()javadoc)必须定义一个等价关系(它必须是自反的,对称的和可传递的)。另外,它必须是一致的(如果未修改对象,则它必须保持返回相同的值)。此外,o.equals(null)必须始终返回false。

hashCode()javadoc)也必须是一致的(如果未根据equals()修改对象,则它必须保持返回相同的值)。

两种方法之间的关系为:


每当a.equals(b)时,a.hashCode()必须与b.hashCode()相同。


在实践中:

如果覆盖一个,则应覆盖另一个。

使用用于计算equals()的同一组字段来计算hashCode()

使用EqualsBuilder库中出色的帮助器类HashCodeBuilderApache Commons Lang。一个例子:

public class Person {
    private String name;
    private int age;
    // ...

    @Override
    public int hashCode() {
        return new HashCodeBuilder(17, 31). // two randomly chosen prime numbers
            // if deriving: appendSuper(super.hashCode()).
            append(name).
            append(age).
            toHashCode();
    }

    @Override
    public 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();
    }
}


还请记住:

使用基于哈希的CollectionMap(例如HashSetLinkedHashSetHashMapHashtableWeakHashMap)时,请确保所放置的键对象的hashCode()当对象在集合中时,进入集合的对象永远不会改变。确保这一点的防弹方法是使密钥保持不变,which has also other benefits

08-06 05:49
查看更多