11

Object.hashCode() 的默认行为本质上是返回对象的“地址”,因此当且仅当 a == b 时 a.hashCode() == b.hashCode()。如果超类已经定义了 hashCode(),如何在用户定义的类中获得这种行为?例如:

class A {
  public int hashCode() {
    return 0;
  }
}

class B extends A {
  public int hashCode() {
    // Now I want to return a unique hashcode for each object.
    // In pythonic terms, it'd look something like:
    return Object.hashCode(this);
  }
}

想法?

4

3 回答 3

26

System.identityHashCode(Object)提供了这种行为。

你会这样写:

class B extends A {
  public int hashCode() {
    return System.identityHashCode(this);
  }
}

请检查 equals 方法,如果两个对象相同,它只返回 true。否则它将破坏为equalshashCode描述的行为。(正确地说,如果您为两个对象获得不同的哈希码,equals 方法必须返回 false。)要提供符合给定 hashCode() 方法的 equals() 实现:

public boolean equals(Object other){
   return this == other;
}
于 2009-06-30T13:28:36.387 回答
9

使用System.identityHashCode(). 这就是IdentityHashMap用途。

但是,您应该非常小心地用 this 覆盖现有hashCode()对象,因为您可能会破坏 hashCode 合同,因为这两个对象是:

如果 a.equals(b) 则 a.hashCode() 必须等于 b.hashCode()

您可能会通过覆盖现有行为来打破这一点,或者您可能也需要覆盖 equals()。

于 2009-06-30T13:28:55.343 回答
1

正如 Mnementh 所说的那样,我只想指出 hashCode() 返回 0 (或任何常量值)是有效的(虽然是蹩脚的)。只有当 !a.equals(b) 时,hashCode() 才能(并且应该)为 a 和 b 返回不同的值。
所以例如你有

class A {
  public int hashCode() {
    return 0;
  }
  public boolean equals(Object o) {
    return o instanceof A; // all objects are equal
  }
}

class B extends A {
  public int hashCode() {
    return System.identityHashCode(this);
  }
  public boolean equals(Object o) {
    return this.hashCode().equals(o.hashCode());
  }
}

现在创建两个对象:

A a = new A();
A b = new B();

突然 a.equals(b),但是 !b.equals(a)。当然,在更现实的生活中,A 中的 equals() 会更复杂,但问题仍然存在。为了摆脱这个问题,你想总是打电话

if (super.equals(o)) return true;

在 new equals() 的开头。

并且由于重写 hashCode() 与重写 equals() 严格相关,因此您要确保 super.equals() 对任何两个给定对象都返回 true,new hashCode() 将返回 super.hashCode()。

于 2009-07-01T13:15:44.723 回答