在语义上而非技术上,实现最佳实践的最佳方法是平等。
在Java中,由于该
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字段,则第2次
fooSet.add(...)应该 没有
其他元素添加到
Set,但应该返回
false,因为
foo1与
foo2具有相同
id。如果定义
Foo.equals(和hashCode)方法包括
两 对
id和
stuff领域那么这可能会被打破,因为
Set可能含有具有相同id字段2点的参考对象。
如果您没有将对象存储在
Collection(或
Map)中,则不必以
equals这种方式定义方法,但是许多人认为它是错误的形式。如果将来您
确实 将其存储在a中,
Collection那么事情将会崩溃。
如果我 需要 测试所有字段的相等性,则倾向于编写另一种方法。诸如此类的东西
equalsAllFields(Object obj)。
然后,您将执行以下操作:
assertTrue(obj1.equalsAllFields(obj2));
另外,一种适当的做法是 不要
定义
equals考虑可变字段的方法。当我们开始谈论类层次结构时,这个问题也变得很困难。如果子对象定义
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:根据可变字段定义相等项”部分:
如何用Java编写平等方法
一些其他链接:
- 实现hashCode()和equals()
- 优美的博客-值,等于和哈希码
哦,仅出于后代考虑,无论您选择比较哪些字段来确定相等性,都需要在
hashCode计算中使用相同的字段。
equals并且
hashCode必须是对称的。如果两个对象相等,则它们 必须 具有相同的哈希码。相反不一定是正确的。



