Reputation: 3415
In the code below why is it that o1.equals(o2);
calls equals(Object o)
not the equals(EqualsTest et)
even though o1
and o2
are referencing objects of type EqualsTest
!
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);
}
}
Upvotes: 3
Views: 202
Reputation: 3411
Since you have used Overloading the methods are linked at compile time and Java uses the less specific argument type for the polymorphic binding to the callee which is object in this case and not EqualsTest.
Upvotes: 1
Reputation: 19185
As I mentioned in the comment it is because of TypeErasure
in java.
Check the byte code which is generated for equalTest
. You can clearly see it will invoke method which has Object
as parameter.
It is same as calling this.equals((Object)et)
which will invoke 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]
What you need is
public static <T extends EqualsTest> boolean equalTest(T o1, T o2) {
return o1.equals(o2);
}
Now Lets check the generated byte code.
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
As you can see compiler has changed Object
to specific type that is EqualsTest
because we have used Bounded Type
so now if you invoke equalTest
it will invoke method with equalTest as parameter
Upvotes: 1
Reputation: 7402
The compiler finds the corresponding method based on the declared type of the argument, not the most specific one. Since you didn't specify anything for thee T
, it defaults to Object
, as @nicholas.hauschild correctly points out.
Upvotes: 1