微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

在编写单元测试时,我经常遇到这样的情况:等于()对于测试中的某些对象(在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必须是对称的.如果两个对象相等,则它们必须具有相同的哈希码.相反的情况并非如此.

原文地址:https://www.jb51.cc/java/124876.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐