我一直认为应该重写 java 中的 .equals() 方法,使其特定于您创建的类。换句话说,寻找两个不同实例的等价性,而不是对同一实例的两个引用。然而,我遇到过其他程序员,他们似乎认为应该保留默认的对象行为,并创建一个新方法来测试同一类的两个对象的等效性。

支持和反对重写 equals 方法的论点是什么?

有帮助吗?

解决方案

如果要测试标准库类中的等效性(例如,确保 java.util.Set 包含唯一元素或使用对象作为 java.util.Map 对象中的键),则必须重写 equals 方法。

请注意,如果您覆盖 equals,请确保遵守文档中所述的 API 合同。例如,确保您还覆盖 对象.hashCode:

如果两个对象根据等值(对象)方法相等,则在两个对象中的每个对象上调用哈希码方法必须产生相同的整数结果。

编辑:我没有将其作为该主题的完整答案发布,因此我将回应 Fredrik Kalseth 的声明,即重写 equals 最适合 不可变对象. 。引用 API 地图:

笔记:如果将可变的物体用作地图键,则必须谨慎行事。如果对象的值以影响对象的方式更改对象的方式,而当对象是地图中的键时,则未指定映射的行为。

其他提示

我强烈建议您拿起一本《Effective Java》并阅读第 7 条,并遵守 等于合同. 。如果要重写可变对象的 equals,则需要小心,因为许多集合(例如 Map 和 Set)使用 equals 来确定等效性,并且改变集合中包含的对象可能会导致意外结果。Brian Goetz 也有不错的 equals 和 hashCode 实现概述.

您不应该“永远”覆盖可变对象的 equals 和 getHashCode - 这适用于 .net 和 Java。如果这样做,并使用这样的对象作为 f.ex 字典中的键,然后 改变 那个对象,你就会遇到麻烦,因为字典依赖哈希码来查找该对象。

这是一篇关于该主题的好文章: http://weblogs.asp.net/bleroy/archive/2004/12/15/316601.aspx

@大卫·施洛斯纳格 提及 提到乔什·布洛赫的 有效的Java - 这是一个 必读 对于任何 Java 开发人员来说。

有一个相关问题:对于不可变值对象,您还应该考虑覆盖 compare_to. 。如果它们不同,标准措辞在 类似的API:

一般情况是这样,但并不严格要求 (compare(x, y)==0) == (x.equals(y))。一般来说,任何违反此条件的比较器都应明确指出这一事实。推荐的语言是“注意:该比较器强加的排序与 equals 不一致。”

Equals 方法旨在比较引用。因此不应重写它来改变其行为。

如果需要,您应该创建一个新方法来测试不同实例中的等效性(或在某些 .NET 类中使用 CompareTo 方法)

老实说,在 Java 中并没有真正反对重写的理由 等于. 。如果您需要比较实例是否相等,那么您就这样做。

如上所述,您需要了解与 哈希码, ,同样,请注意周围的陷阱 可比 界面 - 几乎在所有您想要的情况下 自然排序 由 Comparable 定义为 与等于一致 (参见 大十进制 规范计数器示例的 api 文档)

创建一个新的方法来决定相等性,除了不使用现有的库类之外,在某种程度上违背了 Java 惯例。

您应该只需要覆盖 equals() 方法,如果您希望在将对象添加到排序数据结构时具有特定行为(SortedSet ETC。)

当你这样做时,你也应该覆盖 hashCode().

这里 以获得完整的解释。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top