问题
I am writing some Junit tests in Android, and if i do this:
public void testSetId(){
Friend friend = new Friend(5);
assertEquals(5,friend.getId());
}
I get an ambiguous method call error.
Ambiguous Method Call: Both AssertEquals(int, int) and AssertEquals(Object, Object) match
Yet If i do this:
public void testSetId(){
Integer ID = 5;
Friend friend = new Friend(ID);
assertEquals(ID, friend.getId());
}
It works. I feel like the second function should be doing the exact same thing.
What is going on here?
回答1:
Before Java 5 there was no autoboxing or auto-unboxing. This meant that if a method foo
had a parameter of type Integer
, the following did not compile
foo(5); // 5 needs to be autoboxed
Similarly, if a method bar
had a parameter of type int
, this did not compile
bar(new Integer(5)); // The Integer needs to be unboxed
When autoboxing and auto-unboxing were introduced, it was essential for existing code to continue to work in exactly the same way as before. Therefore when the compiler decides which method is being called, it first considers only the applicable methods that do not require autoboxing or auto-unboxing. Only if there are no such methods does the compiler consider methods requiring autoboxing and/or auto-unboxing.
Since getId
returns an Integer
, the Object
, Object
method can be called without autoboxing in the case when the first argument is also an Integer
. However the int
, int
method can only be called by auto-unboxing the second parameter. Therefore in your second example, the Object
, Object
overload is selected on the first pass.
In your first example, you are trying to pass an int
and an Integer
. The int
, int
method applies only by auto-unboxing the second argument, while the Object
, Object
method applies only by autoboxing the first argument. Therefore the overload cannot be chosen on the first pass, and because neither method is more specific than the other (you'll need to look that last bit up) the compiler cannot choose between the two methods.
Overload resolution is extremely complicated, and I've actually simplified it quite a bit (there are also rules involving var-args). However in practice, you don't need to learn all these rules - if ever you need to tell the compiler which method to apply you can always include an explicit cast or casts:
assertEquals((Integer) id, friend.getId());
来源:https://stackoverflow.com/questions/46837141/ambiguous-method-call-with-integer