【问题标题】:Why override equals instead of using another method name为什么覆盖等于而不是使用另一个方法名称
【发布时间】:2015-01-21 10:20:49
【问题描述】:

这似乎是一个愚蠢的问题,但为什么我们要覆盖equals 方法而不是创建一个具有新名称的新方法并使用它进行比较?

如果我没有覆盖 equals,这意味着 == 和 equals 检查两个引用是否都指向同一个内存位置?

【问题讨论】:

  • 使用 available equals() 方法的数据结构怎么样?示例地图,集合?
  • 您也可以使用不同的名称实现toString()。但是没有其他代码(除了你自己的)会使用它。
  • 非常感谢大家:)
  • 顺便说一句,我不认为这是一个愚蠢的问题。我认为理解 Java 对象模型很重要。

标签: java


【解决方案1】:

这似乎是一个愚蠢的问题,但为什么我们要覆盖 equals 方法而不是创建一个具有新名称的新方法并使用它进行比较?

因为所有标准集合(ArrayListLinkedListHashSetHashMap、...)在确定两个对象是否相等时都使用 equals

如果您发明了一种新方法,这些集合将不会知道它并且不会按预期工作。

理解以下内容非常重要:如果一个集合(如ArrayList)调用Object.equals,此调用将在运行时解析为被覆盖的方法。因此,即使您发明了集合不知道的类,它们仍然可以在这些类上调用方法,例如 equals

如果我没有覆盖 equals,这意味着 == 和 equals 检查两个引用是否都指向同一个内存位置?

是的。 Object.equals 的实现只是执行== 检查。

【讨论】:

  • 最后一件事。如果我制作了两个这样的字符串 //String a = "Hello";字符串 b = "你好";这意味着 a 和 b 引用都指向同一个对象?所以我可以随时使用 equals() 来比较它们而不覆盖它?
  • Strings are special 在 Java 中。如果您执行String a = "Hello"; String b = "Hello";,那么== 将起作用。
  • 明白了,这就是为什么 == 不能用于比较两个字符串内容的原因:)
  • 对。一般来说,你不能在比较字符串时使用 == :-)(如果你有编译时间常量,它可能工作。)一般来说,在解释/考虑 equals vs 时,字符串不适合用作示例==。
【解决方案2】:

如果您使用依赖等于的类,例如HashMapHashSetArrayList 等,则覆盖等于...

例如,如果您将类的元素存储在 HashSet 中,如果您希望不通过简单的引用相等来确定元素的唯一性,则必须覆盖 hashCodeequals

是的,如果您不覆盖 equals,则默认的 equals 实现(在 Object 类中实现)与 == 相同。

【讨论】:

    【解决方案3】:

    除了已经在其他答案中给出的主要原因之外,还要考虑程序的可读性。

    如果您覆盖equalshashCode,任何阅读您代码的人都知道这些方法的用途。这样做会告诉读者类实例之间值相等的标准。阅读您使用 equals 的代码的人会立即知道您正在检查值是否相等。

    如果您使用其他名称,它只会让读者感到困惑,并花费他们额外的时间阅读您的 JavaDocs 以了解您的方法的用途。

    【讨论】:

      【解决方案4】:

      因为equals()Object 类的方法,它是所有类的超类,因此它固有地存在于您编写的每个类中。因此,每个集合类或其他标准类都使用equals() 进行对象比较。如果您希望其他类支持您的自定义类对象的相等性,则必须仅覆盖equals()(因为其他类知道对象比较调用equals())。如果您只使用自己的类,则可以创建一个新方法并确保所有内容都使用您的自定义方法进行比较。

      【讨论】:

        【解决方案5】:

        equals 和 hashcode 方法是特殊方法,广泛用于 java 的实用程序类,特别是集合框架,以及 wrpper 类,例如字符串,整数已经覆盖了这个方法,例如如果您要在 HashSet 中放置您选择的任何具有正确 equals 和 hashcode 实现的对象,为了保持唯一性的属性,hashcode 将与 hashset 中的所有现有对象进行比较,如果它找到任何匹配的 hashcode 然后它看起来进入 equals 方法以仔细检查两者是否真的相等,如果相等检查也通过,则传入对象被拒绝,但如果哈希码相等检查未通过,则 hashset 将不会使用 equals 方法并直接放置该对象进入哈希集。所以我们需要确保equals和hashcode的实现在逻辑上是正确的。

        【讨论】:

          【解决方案6】:

          HashMap<T,U> 这样的类需要有一些方法来识别集合中的哪个项目(如果有的话)应该被认为等同于给定的项目。有两种通用的方法可以做到这一点:

          1. 要求存储在集合中的任何内容都必须包含虚拟方法来执行此类比较(并且最好提供分配部分等价类的快速方法(例如hashCode())。

          2. 要求创建集合的代码必须提供一个对象,该对象可以接受对其他对象的引用并对它们执行与等价相关的操作。

          本来可以从Object 中省略equalshashCode(),并且像HashMap 这样的类型只能用于实现包含此类成员的equatable 接口的键类型;希望使用由身份键入的引用集合的代码必须改用IdentityHashMap。这样的设计不会是不合理的,但是目前的设计使得使用HashMap 的通用集合类型可以用于按价值和身份比较的东西,而不是必须为 collection-of-HashMap 和 collection-of-IdentityHashMap 定义单独的类型。

          另一种设计可能是有一个GeneralHashMap 类型,其构造函数需要指定一个比较函数,并让IdentityHashMapHashMap 都派生自该类型;后者会将其类型限制为equatable,并将其标识函数链接到其中包含的对象的标识函数链。这种设计可能没有什么特别的问题,但事情并非如此。

          在任何情况下,都需要有一些标准方法,集合可以通过这些方法识别应该被视为等效的项目;使用虚拟equals(Object)getHashCode() 是一种方法。

          【讨论】:

            【解决方案7】:

            问题 1

            有两件事。 equals() 位于 Object 类中 比较对象时使用equals()hashcode() 方法的集合框架

            问题 2

            是的,用于比较两个对象。但是当您使用equals() 比较两个字符串对象时,它只检查值。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-11-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2011-02-28
              • 2018-05-02
              • 2020-04-11
              相关资源
              最近更新 更多