2017-03-09 42 views
1

我碰到过这段代码。我从来没有见过以这种方式实施的平等。让我感到震惊的是,它确实是“整洁”的,从某种意义上说,这只是一行样板。这是否合法?

但是,我从未见过这种方法的事实让我感到怀疑。根据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); 
} 
+0

那么,你检查这是否是相同的实例,或者如果这是一个实例(如果它在同一场合不是null),然后比较哈希。这似乎不是一个坏主意,但我可能会错过一些东西 – AxelH

+0

还要确保你真的想使用'instanceof'而不是'getClass()' - 参见http://stackoverflow.com/q/596462/2513200以选择参数或另一个。当使用'instanceof'时,意外地打破对称是非常容易的。 – Hulk

回答

1

这可能是一个坏主意,因为其他答案中已经提到的原因。

至于“法律”方面,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(null)应该返回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,有很多点将被视为相等。


还看到有人绊倒散列碰撞与Objects.hash创造了Strings哈希这个例子equals and hashCode: Is Objects.hash method broken?

5

这是由你自己定义的标准,根据哪个类别的两个实例被认为是彼此相等的。

但是,你应该考虑pageTrackingRequest的不同组合,searchId & productId属性可能导致相同的散列码,你可能不想考虑这些不同的组合为彼此相等。 equals要求所有3个属性分别相等,这可能更有意义。

1

您应该单独检查属性值,而不是仅检查hashCode。有可能两个完全不同的objects导致相同的hashCode不相等。

而且,equals不应完全依赖于hashCode,例如,如果hashCode方法被改变为如下:

@Override 
public int hashCode() 
{ 
    return 31; 
} 

equals方法将开始返回true为这不应该是案件的所有对象。

+0

......这对于'hashCode'来说是一个完全合法的实现(当然是非常糟糕的)。 – Hulk

0

这种方法是错误的。哈希码相等性并不确定,因为不相等的对象可能具有相同的哈希值。这是一个设计错误。