3

@Edit:我正在使用这个库http://jqno.nl/equalsverifier/来检查是否正确equals编写hashCode

假设我们有这个类:

final class Why {
    private final int id;
    private final String name;

    Why(final int id, final String name) {
        this.id = id;
        this.name = name;
    }

    @Override
    public boolean equals(final Object o) {
        if (this == o) return true;
        if (!(o instanceof Why)) return false;

        final Why why = (Why) o;

        if (id != why.id) return false;
        return name != null ? name.equals(why.name) : why.name == null;
    }

    @Override
    public int hashCode() {
        return id;
    }
}

hashCode我只在id现场中继,因为这会给我很好的非冲突哈希。值得注意的是这种hash方法符合所有规则equals-hashCode。我不想用求和哈希做一些花哨的技巧,即:

@Override
public int hashCode() {
    int result = id;
    result = 31 * result + (name != null ? name.hashCode() : 0);
    return result;
}

那么你能解释一下为什么EqualsVerifer默认需要使用equals方法中的所有字段hashCode吗?

java.lang.AssertionError: Significant fields: equals relies on subValue, but hashCode does not.
4

1 回答 1

4

免责声明:我是 EqualsVerifier 的创建者。

它之所以成为默认行为,是因为它通常是一种很好的做法,而 EqualsVerifier 希望鼓励其用户遵循良好的做法。您希望 hashCode 分布尽可能大,以确保在使用基于散列的集合时具有良好的性能。

如果您有充分的理由做其他事情(并且从您的问题来看,似乎您可能有一个),您始终可以通过添加来禁用此行为.suppress(Warning.STRICT_HASHCODE)

但我仍然想知道:如果你觉得有必要name在你的 equals 方法中包含,显然你id的方法不是唯一的。那么为什么不包括name在 hashCode 中呢?这并没有太多额外的工作,特别是因为您可以从 IDE 生成一个,或者简单地使用java.util.Objects.hash(id, name).

于 2017-11-11T11:43:57.543 回答