java – 为equals()实现选择字段的最佳做法
在编写单元测试时,我经常遇到这样的情况:等于()对于测试中的某些对象(在assertEquals中)应该与实际环境中的工作方式不同.例如一些接口ReportConfig.它有id和其他几个字段.逻辑上,一个配置等于另一个配置,当它们的ids匹配时.但是当谈到测试一些具体的实现时,比如说XmlReportConfig,显然我想匹配所有的字段.一个解决方案不是在测试中使用equals,只需迭代对象属性或字段并对它们进行比较,但它似乎不是一个好的解决方案.
所以,除了这种具体的情况,我想弄清楚什么是最好的做法来实现平等,语义上而不是技术上的. 解决方法
在Java中,equals方法真的应该被认为是“identity equals”,因为它与Collection和Map实现的集成.考虑以下几点: public class Foo() { int id; String stuff; } Foo foo1 = new Foo(10,"stuff"); fooSet.add(foo1); ... Foo foo2 = new Foo(10,"other stuff"); fooSet.add(foo2); 如果Foo身份是id字段,那么第二个fooSet.add不应该在Set中添加另一个元素,而应该替换第一个元素,因为它们具有相同的id.如果定义Foo.equals(和hashCode)方法同时包含id和stuff字段,那么这将被破坏,并且Set可能包含对具有相同id字段的对象的2个引用. 如果您没有将对象存储在集合(或映射)中,那么您不需要以这种方式定义equals方法,但是许多人认为它是坏的形式.如果将来你会将其存储在一个集合中,那么事情就会中断. 如果我需要测试所有字段的相等性,我倾向于写另一种方法.像equalsAllFields(Object obj)等等. 那么你会做一些像: assertTrue(obj1.equalsAllFields(obj2)); 另外,适当的做法是不定义考虑到可变字段的equals方法.当我们开始谈论类层次结构时,问题也变得困难.如果一个子对象将equals定义为它的局部字段和基类的组合,那么它的对称性已被违反: Point p = new Point(1,2); // ColoredPoint extends Point ColoredPoint c = new ColoredPoint(1,2,Color.RED); // this is true because both points are at the location 1,2 assertTrue(p.equals(c)); // however,this would return false because the Point p does not have a color assertFalse(c.equals(p)); 在这个伟大的页面中,我会强烈推荐的一些更多的阅读是“陷阱#3:在可变字段方面定义平等”部分:
一些额外的链接: > Implementing hashCode() and equals() 哦,只是为了后代,无论你选择什么字段进行比较来确定平等,你需要在hashCode计算中使用相同的字段. equals和hashCode必须是对称的.如果两个对象相等,则它们必须具有相同的哈希码.相反的情况并非如此. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |