2017-10-13 67 views
0

Java中是否有任何内置合同检查对于hashcode和equals函数之间的契约?Java合同检查 - 内置?例如。哈希码/等于

对于这个问题,让我们坚持以hashcode/equals合同为例,但我一般感兴趣的是合同检查。我曾在多个地方读取equals和hashCode必须满足Java中的“合同”:

  • 的Equals必须遵循的equivalence relation的三个规则,也必须是在重复调用一致
  • 相等对象意味着等于哈希码

我了解条件,而且他们对我有意义。但是,我想知道,这仅仅是一个写在纸上的合同 - 本质上是开发人员不写出错误代码的强有力的指导原则 - 或者它会被Java作为编译时或运行时异常捕获的东西?

+1

它不会被Java作为编译时或运行时异常捕获。 (编写代码)坚持继续RACT。 – nbokmans

+0

如果等于相同并不意味着哈希码相同,那么你可以得到一些奇怪的行为。例如。相同的对象可以映射到散列映射中的不同桶。 –

+0

谢谢你们,那就是我的想法。所以对于Java而言,它基本上是一个强有力的指导方针,不会编写那些将会非常糟糕和错误的代码......但是我们仍然可以在理论上编写一个违反合同的程序,并且它可以编译并运行良好,多年来没有任何错误变得明显。 –

回答

1

它不会在编译时执行。

某些类可能会在运行时强制执行 - 例如,您可以编写一个方法来检查两个相等的对象是否具有相同的哈希码或发送异常。

另请注意,有些情况下您可能想故意偏离推荐的合同。

+0

谢谢。我真的很想看到一个例子,在这个例子中,这个合同实际上是可取的吗? –

+0

例如'Comparable'“强烈建议”compareTo'与'equals'(即'(a.compareTo(b)== 0)==(a.equals(b)')一致。偏离这个建议是有用的,例如:https://stackoverflow.com/a/14534751/829571 – assylias

1

这是不是(不能够)自动夹在编译或运行时(除非你明确地检查它

简单的反例:

public boolean equals(Object other){ 
    return new Random().nextInt(3) == new Random().nextInt(3); 
} 

public int hashCode() { 
    return new Random().nextInt(3); 
} 

然而,它是一个好主意,创建单元测试来检查这些合同我遇到了由于使用严重实现的equals/hashcode而难以发现的错误

+0

是的,我越想越多,我越发觉这不能被自动捕获。我想知道是否有任何框架试图在编译时检查这个违反合同的情况,这将是一个有趣的项目 –

+1

如果你对这方面的某些东西感兴趣,请查看https: //en.wikipedia.org/wiki/Java_Modeling_Language –

+0

不错!非常有趣,它看起来像允许你至少用一种自然的方式指定这些联系人,像Hoare triples这样的方式,然后将其转换为运行时断言。我怀疑是否有可能编写一个通用的工具,它可以在编译时为任何JML规范提供YES/NO答案 - 可能是像计算机科学中大多数这些常规事物一样的不可判定的问题。无论如何,非常有趣。愿望行业更多地使用这一点。 –