通过equals& amp区分子类。哈希码

时间:2014-03-17 06:17:40

标签: java equals hashcode

我正在寻找关于覆盖子类中的hashcode和equals的指导。

我在这里找到了类似的问题:Overriding equals() & hashCode() in sub classes ... considering super fields

但我想要的是略有不同。

想象一下这个(有点愚蠢)的例子:

class Food {

  String name;

  @Override
  public boolean equals(Object obj) {
    if (obj instanceof Food) {
      Food other = (Food)obj;
      return name.equals(other.name);
    }
    return false;
  }

  @Override
  public int hashCode() {
    return name.hashCode();
  }
}

class Vegetable extends Food {
  // No additional fields here
  // Some methods here
}

class Fruit extends Food {
  // No additional fields here
  // Some methods here
}

鉴于:

  1. 子类不添加任何额外字段
    • 至少在这个例子中,它们基本上只是标记类
  2. 具有相同名称的FruitVegetable不应该相等
  3. 问题:

    1. 您是否希望子类等于仅包含instanceof子类检查和对super.equals的调用?
    2. 如果要使具有相同名称的FruitVegetable个实例具有不同的哈希码,那么哈希码应如何构建?

2 个答案:

答案 0 :(得分:2)

您可以在.getClass() Foo中使用.equals()

@Override
public final boolean equals(final Object obj)
{
    if (obj == null)
        return false;
    if (this == obj)
        return true;
    // Class<?> are signletons, therefore we can use ==/!=
    if (getClass() != obj.getClass())
        return false;
    return name.equals(((Foo) obj).name);
}

.getClass()将返回对象的类,因此FruitVegetable,甚至Food

对于.hashCode()name.hashCode()没问题。不要忘记不要求两个不是.equals()的对象的哈希码不同。但如果你愿意,那么.getClass()也可以在这里使用:

@Override
public final int hashCode()
{
    return 31 * getClass().hashCode() + name.hashCode();
}

答案 1 :(得分:1)

  
      
  1. 您是否希望equals只包含一个检查实例和对super.equals的调用?
  2.   

instanceof在这里很危险,因为Food不是抽象的。这意味着equals不对称。

someFruit.equals(someFood) // will be false
someFood.equals(someFruit) // will be true

这可能不是转入问题,但这是你应该考虑的事情。

如果您不想违反合同,Food应检查是否this.getClass() == obj.getClass()。如果你这样做,那么你也不一定需要在子类中覆盖它。

否则它并不重要。该方法是按合同定义的,您可以根据需要实现它。

  
      
  1. 如何构建哈希码以尝试使用相同名称的Fruit and Vegetable实例具有不同的哈希码?
  2.   

他们不需要与众不同。