所以,除了这种具体的情况,我想弄清楚什么是最好的做法来实现平等,语义上而不是技术上的.
解决方法
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必须是对称的.如果两个对象相等,则它们必须具有相同的哈希码.相反的情况并非如此.