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

对象javadocs和Josh Bloch告诉我们如何实现hashCode / equals,好的IDE将正确处理各种类型的字段。 关于这一切的一些讨论。

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

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

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

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

这个问题似乎提供了一个潜在的答案。

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

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

你要为每个想要保护的课程编写unit testing怎么样? unit testing应该

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

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

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

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

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

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

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

不幸的是,我不知道有任何插件可以做到这一点,不过我肯定会看看。

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

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

  • 项目Lombok – Eclipse插件也可以使用构建工具提供equals()hashCode()和其他样板代码的自动生成 – 因为它是在编译时生成的,对类的任何更改都会自动更新这些方法
  • equalsverifier – 提供一种使用reflection自动unit testingequals() – 不支持测试hashCode()