【问题标题】:Why is it better to use the default Object equals method in Java?为什么在 Java 中使用默认的 Object equals 方法更好?
【发布时间】:2012-11-25 16:10:37
【问题描述】:

为什么认为在 Java 中使用默认的 Object equals 方法并对其进行修改以使其适用于特定类会更好(通过使用 instanceof 进行验证并使用类型转换):

public boolean equals(Object otherObject)
{
   boolean isEqual = false;

   if ((otherObject != null) && (otherObject instanceof myClass))
      {
         myClass classObject = (myClass)otherObject;

         if (.....) //checking if equal
         {
            .....
}

而不是使用新的 equals 方法重载它,该方法特定于需要使用 equals 的每个类:

public boolean equals(myClass classObject)

【问题讨论】:

  • 这不是更好,它只是检查相等的真正含义。
  • 我认为 OP 会问为什么使用 equals(Object) 而不是 equals(MyClass)

标签: java overriding overloading equals


【解决方案1】:

Object.equals() 的签名是public boolean equals(Object)。如果您定义了一个方法public boolean equals(MyClass),您将添加一个具有不同签名的新方法,而不是覆盖(或重新定义,如果您愿意)Object.equals() 方法。

由于所有集合都调用Object.equals() 方法,因此除了您自己的代码之外,任何人都不会调用您的新方法,因此几乎没有用处。例如,如果你创建一个Set<MyClass>,它会认为两个实例是不同的,尽管你的equals(MyClass) 方法认为它们是相等的。

【讨论】:

  • 我认为 OP 假设多态性会调用正确的方法,也许你可以解释为什么不是这样。
  • @sjr.. 他已经解释过了。将它与动态调度混合是没有意义的,因为它不是有效的覆盖。使用equals 比较对象的集合将始终调用Object 类方法。
  • 我认为如果您对 Java 了如指掌,这是一个很好的答案。我认为 OP 没有,所以这对他来说可能是新闻。
  • 问题是我不认为它是一种通用的equals 方法,而是一种特定于类的方法。据我了解equals(Object) 更好,因为它是一种通用的比较方法。但是当我只使用 1 个超类和 3 个派生类时,这并不重要。我说的对吗?
  • 您可以定义一个equals(MyClass) 方法。请注意,标准集合不会使用它,而只能由您自己的代码使用。例如,如果您创建一个Set<MyClass>,它会认为两个实例是不同的,尽管您的 equals(MyClass) 方法认为它们是相等的。
【解决方案2】:

这是因为 Java 中的大多数类(列表、队列、地图等)都使用 boolean equals(Object obj) 方法。在九十年代设计 Java 的时候,泛型还不存在。

使用例如ComparatorComparable 的比较方法已更新为支持泛型,因此可以直接采用您的类的正确类型(避免使用instanceof)。 Object.equals() 只需要一个通用的Object

如果您使用新签名重载.equals(),其他集合将不知道您的新equals() 方法,并且仍会调用Object 提供的旧原始方法,因此您必须坚持使用它并使用instanceof。请记住,重载与覆盖没有相同的效果。在覆盖子类方法时被调用,因为它具有完全相同的签名。在重载中,您只是提供具有不同签名的替代功能,因此调用者必须知道它。

或者,您可以不使用equals() 方法,而是稍微更改您的代码以使用带有泛型的较新比较方法。大多数集合已更新为支持 ComparatorComparable 等。

【讨论】:

  • 感谢您的解释,现在我明白为什么它应该被覆盖而不是重载。
  • Comparable 是在 Java 2 中引入的,早在 Java 5 中添加泛型之前很久,在 Java 5 中 Compable 和整个集合框架都使用泛型进行了改造,而不会失去向后兼容性。
  • @meriton 是的,Comparable 一直存在,但它已使用 Java 5 更新为泛型,而 .equals() 没有,如果您想比较类型,仍然需要 instanceof。对不起,如果措辞有点误导。
【解决方案3】:

如果您使用public boolean equals(MyClass classObject),您将重载
所以你的方法不会被调用,因为它没有覆盖
您可以创建这样的方法,但您还需要 equal(Object) 以使一切正常运行(集合等)。

您对这种方法感兴趣的唯一原因是性能。但我不认为现在你使用equals(Object) 有问题

【讨论】:

    【解决方案4】:

    你必须为你的类重写 equals 方法。当你重写一个方法时,你不能改变方法参数,不能改变返回类型,也不能使方法的可访问性更严格。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多