在阅读之后(再次,应该已经做了很久以前)正确实现了equals和hashcode我得出了这些结论,这对我有用:
如果是JDK 7之前:更喜欢使用Apache commons equalsbuilder和hashcodebuilder。 (或番石榴)。 他们的javadoc包含了如何以良好的方式使用它们的例子。
如果是JDK 7 ++ :使用新的Objects实用程序类
但是,如果为hibernate写作会出现一些特殊的请求(请参阅更远的来源) 其中推荐使用 instanceof 而不是 getClass ,因为hibernate创建了延迟加载的子类的代理。
但据我所知,如果这样做会发生另一个潜在的问题:使用getClass的原因是为了确保equals合约的对称属性。的JavaDoc:
*It is symmetric: for any non-null reference values x and y, x.equals(y)
should return true if and only if y.equals(x) returns true.*
通过使用instanceof,它可能不是对称的。 示例:B扩展A. A的等于A的检查实例.B的等于检查B的实例。给A和B b:
a.equals(b) - >真正 b.equals(a) - >假
如何使用hibernate实现equals而不会失去对称属性的风险?使用getClass时我似乎不安全,使用instanceof时我不安全吗?
答案是永远不要将重要成员添加到子类,然后使用instanceof是安全的(对于hibernate)?
我读到的消息来源:
What issues should be considered when overriding equals and hashCode in Java?
Josh Blochs的第7和第8项优秀书籍“Effective Java”,http://web.archive.org/web/20110622072109/http://java.sun.com/developer/Books/effectivejava/Chapter3.pdf
关于Java 7:http://www.javacodegeeks.com/2012/11/guavas-objects-class-equals-hashcode-and-tostring.html
答案 0 :(得分:4)
如果要比较equals方法中两个对象的类,可以在比较它们之前对两个对象使用Hibernate.getClass。那你就不会遇到麻烦,例如比较对象和对象的hibernate代理时。
答案 1 :(得分:3)
在进行了一些调查后,我总结了这个问题:
Langers说http://www.angelikalanger.com/Articles/JavaSolutions/SecretsOfEquals/Equals.html
- 测试的instanceof仅对最终类是正确的,或者至少方法equals()在超类中是最终的。后者本质上 意味着没有子类必须扩展超类的状态,但可以 仅添加与对象无关的功能或字段 状态和行为,例如瞬态或静态字段。
另一方面,使用getClass()测试的实现总是如此 遵守equals()合同;他们是正确和强大的。他们 然而,在语义上与实现非常不同 使用instanceof测试。使用getClass()的实现不允许 子类与超类对象的比较,甚至不是子类时 不添加任何字段,甚至不想覆盖equals()。 这种“普通的”类扩展例如是添加的 一个子类中的调试打印方法,正是为这个“微不足道”而定义的 目的。如果超类禁止通过混合类型比较 getClass()检查,那么普通的扩展将无法比较 到它的超类。这是否完全取决于问题 类的语义和扩展的目的。
摘要 - 使用finalof和final for equals可以避免破坏对称性,并避免出现休眠“代理”问题。
链接
答案 2 :(得分:2)
这是一个有趣的问题 - 在涉及继承时,将equals
实现为等价关系并非易事。见Martin Odersky等人的this in-depth post。关于实现对象平等。