Ambiguous method call with Integer

橙三吉。 提交于 2021-01-05 06:37:40

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!