这等于合法吗?

2022-05-16 00:00:00 equals java

我遇到了这段代码。我从来没有见过Equals以这样的方式实现。让我印象深刻的是,它真的很"整洁",从这个意义上说,它只需要一行样板。

然而,我以前从未见过这种方法,这让我产生了怀疑。根据Java Equals和hashCode的合同,以下实现合法吗?

@Override
public boolean equals(Object o)
{
  return this == o || o instanceof DetailsPageTrackingRequest 
  && this.hashCode() == o.hashCode();
}

@Override
public int hashCode()
{
  //java.util.Objects
  return Objects.hash(pageTrackingRequest, searchId, productId);
}

解决方案

由于其他答案中已经说明的原因,这可能不是一个好主意。

至于"法律"方面,Contract of Object.equals说明

Equals方法在非空对象引用上实现等价关系:

  • 它是自反式的:对于任何非空的引用值x,x.equals(X)应返回True。
  • 它是对称的:对于任何非空的引用值x和y,当且仅当y.equals(X)返回True时,x.equals(Y)才应返回True。
  • 它是可传递的:对于任何非空的引用值x、y和z,如果x.equals(Y)返回True,y.equals(Z)返回True,则x.equals(Z)应返回True。
  • 它是一致的:对于任何非空的引用值x和y,多次调用x.equals(Y)将一致返回True或一致返回False,前提是对象上的等于比较中使用的信息未被修改。
  • 对于任何非空引用值x,x.equals(空)应返回FALSE。

逐步:

  • 自反式:是的,由于this == o
  • 对称:由于使用了instanceof,我们需要查看所有超类和子类以确保
  • 传递性:取决于对称要求,否则为是
  • 一致:是
  • x.equals(null)应返回FALSE:是,由于instanceof

因此,从纯粹的法律角度来看,这取决于继承层次结构中的其他实现是否违反了对称性和传递性--请参阅Any reason to prefer getClass() over instanceof when generating .equals()?的答案。

除此之外,考虑到hashCode不需要为非等价实例生成不同的值,这通常不是定义相等的好方法。


示例:

具有两个字段的不可变点类xy

class Point {
    final int x;
    final int y

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
->有2^32 * 2^32 = 2^64个不同的状态,但只有2^32个可能的哈希码。这意味着,根据equals的实现,有许多点被视为相等。


另请参阅此示例equals and hashCode: Is Objects.hash method broken?,了解有关使用Objects.hashStrings创建的散列的散列冲突的问题。

相关文章