有什么方法可以使hashCode / equals与类的业务定义保持一致?

时间:2011-10-09 14:02:06

标签: java hashcode

对象javadocs和Josh Bloch告诉我们应该如何实现hashCode / equals,好的IDE将正确处理各种类型的字段。关于所有问题的一些讨论是here

这个问题是关于下一步:你如何确保他们保持良好?

特别是,我觉得对于大多数类来说,equals / hashCode应该像Bloch建议的那样实现(以及Eclipse和其他IDE的实现),并考虑到该类中所有非派生的业务逻辑字段。在将新字段添加到类中作为继续工作的一部分时,人们常常忘记将它们添加到equals / hashCode实现中。当两个对象看起来相等时,这可能导致难以发现的错误,但实际上不同于最近引入的字段的值。

如果成员字段发生变化,团队(甚至一个团队!)如何帮助确保类中的equals / hashCode继续考虑所有相关字段?

我知道Apache的EqualsBuilder和HashCodeBuilder可以使用反射,这显然会考虑正确的字段,但我想避免使用它们的性能成本。是否有其他方法来标记未包含在equals / hashCode中的字段,应该是什么?静态代码分析,IDE功能,单元测试技术?

6 个答案:

答案 0 :(得分:8)

从未尝试过,但http://code.google.com/p/equalsverifier/怎么样?

答案 1 :(得分:7)

似乎在this question中提供了一个可能的答案。

我没有多关注Project Lombok,但我立即想到,嗯注释可以用于代码生成器。

答案 2 :(得分:1)

如何为每个要保护的课程编写单元测试。 单元测试

  1. 使用反射来计算字段数,并与本地存储的字段名称(和类型)进行比较。
  2. 如果检测到字段数(或字段类型)发生更改,则调用哈希码。如果值相同,则测试用例失败。提醒开发人员已更改类的字段,并且开发人员应该:更新equals和Hashcose,并更新un​​ittest。
  3. 确保unittest在每晚构建中运行。

答案 3 :(得分:0)

您不需要在哈希码方法中包含每个字段。如果您在哈希码算法中使用了多个字段,则它可能会保持良好状态。我见过的IDE生成的算法使用随机(在实现时,而不是在执行时)的素数常量值,所以只需确保可能最终在同一个映射或树中的类(例如,它们实现相同的) interface)具有不同的常量值。当然,除非你想在接口级别上保持相等。

我从来没有见过哈希码算法“变坏” - 你担心这个问题不成比例。

答案 4 :(得分:0)

听起来你正在寻找的是IDE中的插件或功能,它执行类的分析并在equals()和hashCode()方法不引用所有相关字段时生成警告。

这基本上会将反射开销转移到IDE,而不是让它在运行时有成本。

不幸的是,我不知道有任何插件会这样做,不过我肯定会看看。

另一方面,这样的自动化工具如何知道哪些字段与业务逻辑相关?你可能需要用类似注释的东西来标记不相关的字段,否则你会发现自己有一些你无法摆脱的警告,但你知道这些警告是不正确的。

编辑:这个答案没用,所以我只是在这里从更好的答案中汇总真正有用的建议:

  • Project Lombok - Eclipse插件也适用于构建工具,可以自动生成equals()hashCode()和其他样板代码 - 因为它是在编译时生成的,任何更改该类将自动更新这些方法
  • equalsverifier - 提供一种使用反射自动对equals()进行单元测试的方法 - 不支持测试hashCode()

答案 5 :(得分:0)

您可以使用使用反射(例如XStream)查找属性的工具将对象序列化为字符串,并将该字符串存储在存储库中。您的单元测试可以重新序列化对象并将结果与​​存储的值进行比较。

作为您自己的过程的一部分,使这些字符串的存储依赖于手动验证您的hashCode和equals正确捕获所有相关值。