Java参数混乱

时间:2012-11-05 17:20:26

标签: java parameters dispatch

在下面的代码中,为什么o1.equals(o2);调用equals(Object o)而不调用equals(EqualsTest et),即使o1o2引用{{1}类型的对象}}!

EqualsTest

3 个答案:

答案 0 :(得分:1)

编译器根据declared type of the argument找到相应的方法,而不是最具体的方法。由于您没有为T指定任何内容,因此默认为Object,正如@ n​​icholas.hauschild正确指出的那样。

答案 1 :(得分:1)

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

答案 2 :(得分:1)

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

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

与调用this.equals((Object)et)

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,它将使用{调用方法{1}}