java - 在 Java 接口(interface)中处理 equals 和 hashCode 的微妙之处

标签 java equals hashcode

我正在为这些接口(interface)实现一个值对象:

interface FooConsumer
{
    public void setFoo(FooKey key, Foo foo);
    public Foo getFoo(FooKey key);
}

// intent is for this to be a value object with equivalence based on 
// name and serial number
interface FooKey
{
    public String getName();
    public int getSerialNumber();
}

从我读到的内容(例如 Enforce "equals" in an interfacetoString(), equals(), and hashCode() in an interface )看来建议是提供一个抽象基类,例如

abstract class AbstractFooKey
{
    final private String name;
    final private int serialNumber
    public AbstractFooKey(String name, int serialNumber)
    {
       if (name == null)
          throw new NullPointerException("name must not be null");
       this.name = name;
       this.serialNumber = serialNumber;
    }
    @Override public boolean equals(Object other)
    {
       if (other == this)
          return true;
       if (!(other instanceof FooKey))
          return false;
       return getName().equals(other.getName() 
          && getSerialNumber() == other.getSerialNumber()
          && hashCode() == other.hashCode();       // ***
    }
    @Override public int hashCode()
    {
       return getName().hashCode() + getSerialNumber()*37;
    }
}

我的问题是关于我在此处添加的最后一点,以及如何处理使用 x 值调用 AbstractFooKey.equals(x) 的情况是实现 FooKey 但没有子类 AbstractFooKey 的类的实例。我不知道如何处理这个问题;一方面,我觉得相等的语义应该只依赖于名称和序列号相等,但看起来 hashCode 也必须相等才能满足 Object.equals() 的约定。

我应该是:

  1. 真的很松懈,只是忘记了标记为***的行
  2. 放松并保留我所拥有的
  3. 如果 other 对象不是 AbstractFooKey,则从 equals() 返回 false
  4. 真的要严格一点,去掉 FooKey 接口(interface)并用一个最终的类替换它吗?
  5. 还有别的事吗?

最佳答案

将所需的语义记录为契约(Contract)的一部分。

理想情况下,您实际上拥有一个最终的实现,这消除了为此特定目的而需要接口(interface)的需求。您可能还有其他原因需要该类型的接口(interface)。

Object的契约(Contract)要求实际上来自hashCode :If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.

您不需要包含 hashCodeequals计算,而是需要包含 equals 中涉及的所有属性在 hashCode计算。在这种情况下,我只是比较 serialNumbername两者皆 equalshashCode .

保持简单,除非你有真正的理由让它复杂化。

从最终的、不可变的类开始。

如果您需要一个接口(interface),请创建一个匹配的接口(interface),并记录语义和默认实现。

关于java - 在 Java 接口(interface)中处理 equals 和 hashCode 的微妙之处,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12802872/

相关文章:

java - 具有相同哈希码但不相等的两个实例

algorithm - 将相似输入映射到相似输出的哈希函数?

java - 将密码存储在 xml security-context.xml 或数据库中的最佳实践?

Scala 设置哈希码

java - 如何检测 JComboBox 中选定的对象?

python - (Python) 直到 a == b

java - 是否可以在运行时访问类型参数上的注释?

c# - Dictionary.Equals() 有实现吗?

java - 指定的 child 已经有一个 parent 。您必须首先在 child 的 parent 上调用 removeView() (Android)

java - 当似乎没有必要时将上下文存储在适配器中