基于身份的Java哈希码

时间:2009-06-30 13:22:53

标签: java identity hashcode

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

想法?

3 个答案:

答案 0 :(得分:26)

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

你会写这个:

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

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

public boolean equals(Object other){
   return this == other;
}

答案 1 :(得分:9)

使用System.identityHashCode()。这是IdentityHashMap使用的内容。

你应该非常警惕用这个覆盖现有的hashCode(),因为你可能会破坏hashCode合同,因为这两个对象:

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

您可以通过覆盖现有行为来解决此问题,或者您也可能需要覆盖equals()。

答案 2 :(得分:1)

正如Mnementh所说的那样,我只想指出hashCode()返回0(或任何常量值)是有效的(虽然是跛脚)。 hashCode()只有在!a.equals(b)的情况下才能(并且应该)为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;

在新的equals()的开头。

由于重写hashCode()严格依赖于重写equals(),因此您需要确保任何两个给定对象的super.equals()返回true,新的hashCode()将返回super.hashCode()。