【问题标题】:java why should equals method input parameter be Objectjava为什么equals方法的输入参数应该是Object
【发布时间】:2020-10-28 23:10:38
【问题描述】:

我正在阅读一本关于数据结构的书。目前我在图表上,下面的代码是图表的顶点部分。

class Vertex<E>{
    //bunch of methods

    public boolean equals(Object o){
         //some code
    }
}

当我尝试实现这个 equals 方法时,我的编译器抱怨不检查参数的类型,只允许发送任何对象。我也觉得有点奇怪,为什么那个参数不应该是一个顶点而不是一个对象。作者这样做是有原因的还是这是一些错误或过时的例子?

【问题讨论】:

  • 你能在这里重复一下exact编译器信息吗?
  • 我看不出你会接受 Object 而不是 Vertex。
  • 我会称之为警告,而不是错误。
  • 值得注意的是,显示的代码不会对我产生任何警告:ideone.com/JNz1g,您可能需要向我们展示实现,以便我们确定为什么您会收到编译器消息关于这个。

标签: java types equals


【解决方案1】:
@Override
public boolean equals(Object obj)
{
     if (!(obj instanceof Vertex)) return false;
     else return // blah blah
}

【讨论】:

  • 首先您可能希望检查 obj 是否为空。
  • @Hovercraft Full Of Eels,@Eng.Fouad:我不同意。当测试对象为空时,instanceof 始终返回 false。因此,对 null 的测试是多余的。
【解决方案2】:

equals(Object) 是根 - Object 中定义的方法。如果您不完全匹配签名,则当有人检查两个对象是否相等时,将调用 Object 的版本。不是你想要的。

您可能已经看到可以使用确切时间的其他方法(例如 Comparator)。那是因为这些 API 是在 Java 5 中通用化的。Equals 不可能是因为用两种不同的类型调用 equals 是有效的。它应该返回 false,但它是有效的。

【讨论】:

    【解决方案3】:

    因为这个方法存在于泛型之前,所以为了向后兼容它必须保持这种方式。

    强制类型的标准解决方法是:

    return obj instanceof MyClass && <some condition>;
    

    【讨论】:

      【解决方案4】:

      equals 是从 Object 继承的方法,被定义为足够灵活,以便您可以获取任何对象并测试它是否等于任何其他对象(因为它理所当然应该能够做到),所以它怎么可能还有什么办法吗?

      编辑 1

      来自 jhlu87 的评论:
      那么写一个输入参数为顶点的equals方法不是很好的形式吗?

      欢迎您为任何方法(包括 equals)创建自己的重载,但在不更改名称的情况下这样做可能会使许多人感到困惑,他们会认为您的 equals 是从 Object 继承的。如果它是我的代码并且我想要一个更具体的 equals 方法,我会将其命名为与“equals”稍有不同以避免混淆。

      【讨论】:

      • 那么写一个输入参数为顶点的equals方法不是很好吗?
      【解决方案5】:

      如果您的方法不采用 Object 类型的参数,则它不会覆盖equals 的默认版本,而是重载它。发生这种情况时,两个版本都存在,Java 根据参数的变量类型(而不是实际的对象类型)决定使用哪一个。因此,这个程序:

      public class Thing {
      
          private int x;
      
          public Thing(int x) {
              this.x = x;
          }
      
          public boolean equals(Thing that) {
              return this.x == that.x;
          }
      
          public static void main(String[] args) {
              Thing a = new Thing(1);
              Thing b = new Thing(1);
              Object c = new Thing(1);
              System.out.println(a.equals(b));
              System.out.println(a.equals(c));
          }
      
      }
      

      第一次比较时会打印出 true(因为 b 是 Thing 类型),而第二次比较会打印 false(因为 c 是 Object 类型,即使它恰好包含 Thing)。

      【讨论】:

        【解决方案6】:

        这是因为作者覆盖了equals。 Equals 在 java.lang.Object 中指定,是所有类继承的东西。

        查看java.lang.Object的javadoc

        【讨论】:

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