加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 为equals()实现选择字段的最佳做法

发布时间:2020-12-14 16:36:10 所属栏目:Java 来源:网络整理
导读:在编写单元测试时,我经常遇到这样的情况:等于()对于测试中的某些对象(在assertEquals中)应该与实际环境中的工作方式不同.例如一些接口ReportConfig.它有id和其他几个字段.逻辑上,一个配置等于另一个配置,当它们的ids匹配时.但是当谈到测试一些具体的实现时,
在编写单元测试时,我经常遇到这样的情况:等于()对于测试中的某些对象(在assertEquals中)应该与实际环境中的工作方式不同.例如一些接口ReportConfig.它有id和其他几个字段.逻辑上,一个配置等于另一个配置,当它们的ids匹配时.但是当谈到测试一些具体的实现时,比如说XmlReportConfig,显然我想匹配所有的字段.一个解决方案不是在测试中使用equals,只需迭代对象属性或字段并对它们进行比较,但它似乎不是一个好的解决方案.

所以,除了这种具体的情况,我想弄清楚什么是最好的做法来实现平等,语义上而不是技术上的.

解决方法

what are best practices to implement equals,semantically,not technically.

在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:在可变字段方面定义平等”部分:

07001

一些额外的链接:

> Implementing hashCode() and equals()
> Graceful Blog – Values,Equals,and Hashcodes

哦,只是为了后代,无论你选择什么字段进行比较来确定平等,你需要在hashCode计算中使用相同的字段. equals和hashCode必须是对称的.如果两个对象相等,则它们必须具有相同的哈希码.相反的情况并非如此.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读