重写equals和hashCode时必须考虑哪些问题/陷阱?


当前回答

逻辑上我们有:

a.getClass().equals(b.getClass()) && a.equals(b) ⇒ a.hashCode() == b.hashCode()

但反之亦然!

其他回答

在检查成员是否相等之前,有几种方法可以检查类是否相等,我认为这两种方法在适当的情况下都是有用的。

使用instanceof操作符。 使用this.getClass () .equals (that.getClass())。

我在最终的等号实现中使用#1,或者在实现指定等号算法的接口时使用#1。util集合接口-检查with (obj instanceof Set)或任何你正在实现的接口的正确方法)。当等号可以被重写时,这通常是一个糟糕的选择,因为这会破坏对称性。

选项#2允许安全地扩展类,而不重写等号或破坏对称性。

如果你的类也是Comparable类,equals和compareTo方法也应该是一致的。下面是Comparable类中equals方法的模板:

final class MyClass implements Comparable<MyClass>
{

  …

  @Override
  public boolean equals(Object obj)
  {
    /* If compareTo and equals aren't final, we should check with getClass instead. */
    if (!(obj instanceof MyClass)) 
      return false;
    return compareTo((MyClass) obj) == 0;
  }

}

超类中有两个方法,如java.lang.Object。我们需要将它们重写为自定义对象。

public boolean equals(Object obj)
public int hashCode()

相等的对象只要相等就必须产生相同的哈希码,然而不相等的对象不需要产生不同的哈希码。

public class Test
{
    private int num;
    private String data;
    public boolean equals(Object obj)
    {
        if(this == obj)
            return true;
        if((obj == null) || (obj.getClass() != this.getClass()))
            return false;
        // object must be Test at this point
        Test test = (Test)obj;
        return num == test.num &&
        (data == test.data || (data != null && data.equals(test.data)));
    }

    public int hashCode()
    {
        int hash = 7;
        hash = 31 * hash + num;
        hash = 31 * hash + (null == data ? 0 : data.hashCode());
        return hash;
    }

    // other methods
}

如果你想了解更多,请点击这个链接http://www.javaranch.com/journal/2002/10/equalhash.html

这是另一个例子, http://java67.blogspot.com/2013/04/example-of-overriding-equals-hashcode-compareTo-java-method.html

玩得开心!@ .@

仍然令人惊讶的是,没有人推荐番石榴库。

 //Sample taken from a current working project of mine just to illustrate the idea

    @Override
    public int hashCode(){
        return Objects.hashCode(this.getDate(), this.datePattern);
    }

    @Override
    public boolean equals(Object obj){
        if ( ! obj instanceof DateAndPattern ) {
            return false;
        }
        return Objects.equal(((DateAndPattern)obj).getDate(), this.getDate())
                && Objects.equal(((DateAndPattern)obj).getDate(), this.getDatePattern());
    }

逻辑上我们有:

a.getClass().equals(b.getClass()) && a.equals(b) ⇒ a.hashCode() == b.hashCode()

但反之亦然!

对于平等的人,可以看看Angelika Langer的《平等的秘密》。我非常喜欢它。她还提供了关于Java泛型的常见问题解答。在这里查看她的其他文章(向下滚动到“核心Java”),在那里她还继续介绍了第2部分和“混合类型比较”。祝你阅读愉快!