小编典典

在 Java 中覆盖 equals 和 hashCode 时应该考虑哪些问题?

all

equals覆盖和时必须考虑哪些问题/陷阱hashCode


阅读 176

收藏
2022-03-06

共1个答案

小编典典

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

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

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

这两种方法之间的 关系是:

无论何时a.equals(b),则a.hashCode()必须与 相同b.hashCode()

在实践中:

如果你覆盖一个,那么你应该覆盖另一个。

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

使用Apache Commons
Lang
库中出色的帮助类EqualsBuilderHashCodeBuilder
一个例子:

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

还要记住:

当使用基于散列的集合映射时,例如HashSetLinkedHashSetHashMapHashtableWeakHashMap,请确保您放入集合中的关键对象的
hashCode()
在对象位于集合中时不会更改。确保这一点的万无一失的方法是使您的密钥不可变,这还有其他好处

2022-03-06