3

在下面的代码中,为什么它不调用o1.equals(o2);即使并且引用类型的对象!equals(Object o)equals(EqualsTest et)o1o2EqualsTest

public class EqualsTest {
      public static <T> boolean equalTest(T o1, T o2) {
          return o1.equals(o2);
      }
      public static void main(String[] args) {
          EqualsTest et1 = new EqualsTest();
          EqualsTest et2 = new EqualsTest();
          System.out.println(et1.equals(et2));
          System.out.println(equalTest(et1, et2));
      }
      public boolean equals(Object o) {
          if (o instanceof EqualsTest) {
              System.out.println("equals(Object)");
              return true;
          }
          return false;
      }
      public boolean equals(EqualsTest et) {
          System.out.println("equals(EqualsTest)");
          return this.equals((Object)et);
      }
}
4

3 回答 3

1

编译器根据参数的声明类型找到对应的方法,而不是最具体的方法。由于您没有为 thee 指定任何内容T,因此它默认为Object,正如@nicholas.hauschild 正确指出的那样。

于 2012-11-05T17:24:21.653 回答
1

由于您使用了重载,因此方法在编译时链接,并且 Java 使用不太具体的参数类型将多态绑定到被调用者,在这种情况下是对象而不是 EqualsTest。

于 2012-11-05T17:27:11.343 回答
1

正如我在评论中提到的,这是因为TypeErasure在 java 中。

检查生成的字节码equalTest。您可以清楚地看到它将调用具有Object作为参数的方法。

与调用this.equals((Object)et)which 将调用相同Object method

// Method descriptor #15 (Ljava/lang/Object;Ljava/lang/Object;)Z
// Signature: <T:Ljava/lang/Object;>(TT;TT;)Z
// Stack: 2, Locals: 2
public static boolean equalTest(java.lang.Object o1, java.lang.Object o2);
0  aload_0 [o1]
1  aload_1 [o2]
2  invokevirtual java.lang.Object.equals(java.lang.Object) : boolean [18]

你需要的是

public static <T extends EqualsTest> boolean equalTest(T o1, T o2) {
    return o1.equals(o2);
}

现在让我们检查生成的字节码。

public static boolean equalTest(EqualsTest o1, EqualsTest o2);
0  aload_0 [o1]
1  aload_1 [o2]
2  invokevirtual EqualsTest.equals(EqualsTest) : boolean [18]
5  ireturn

如您所见,编译器已更改Object为特定类型,这是EqualsTest因为我们已经使用Bounded Type了,所以现在如果您调用equalTest它将调用方法equalTest as parameter

于 2012-11-05T17:41:01.770 回答