Java 带有整数的不明确方法调用

Java 带有整数的不明确方法调用,java,android,junit,ambiguous,Java,Android,Junit,Ambiguous,我正在用Android编写一些Junit测试,如果我这样做: public void testSetId(){ Friend friend = new Friend(5); assertEquals(5,friend.getId()); } public void testSetId(){ Integer ID = 5; Friend friend = new Friend(ID); assertEquals(ID, friend.getId()); }

我正在用Android编写一些Junit测试,如果我这样做:

public void testSetId(){
    Friend friend = new Friend(5);
    assertEquals(5,friend.getId());
}
public void testSetId(){
    Integer ID = 5;
    Friend friend = new Friend(ID);
    assertEquals(ID, friend.getId());
}
我得到一个不明确的方法调用错误

不明确的方法调用: AssertEquals(int,int)和 AssertEquals(对象,对象)匹配

但如果我这样做:

public void testSetId(){
    Friend friend = new Friend(5);
    assertEquals(5,friend.getId());
}
public void testSetId(){
    Integer ID = 5;
    Friend friend = new Friend(ID);
    assertEquals(ID, friend.getId());
}
它起作用了。我觉得第二个函数应该做完全相同的事情


这是怎么回事?

在Java 5之前,没有自动装箱或自动取消装箱。这意味着如果一个方法
foo
有一个类型为
Integer
的参数,那么下面的代码不会编译

foo(5);    // 5 needs to be autoboxed
bar(new Integer(5));    // The Integer needs to be unboxed
类似地,如果一个方法
bar
有一个类型为
int
的参数,那么它不会编译

foo(5);    // 5 needs to be autoboxed
bar(new Integer(5));    // The Integer needs to be unboxed
当引入自动装箱和自动取消装箱时,现有代码必须以与以前完全相同的方式继续工作。因此,当编译器决定调用哪个方法时,它首先只考虑不需要自动装箱或自动取消装箱的适用方法。只有当没有这样的方法时,编译器才会考虑需要自动装箱和/或自动解压的方法。 由于
getId
返回一个
整数
,因此当第一个参数也是
整数
时,可以调用
对象
对象
方法而无需自动装箱。但是,
int
int
方法只能通过自动取消绑定第二个参数来调用。因此,在第二个示例中,在第一次通过时选择了
对象
对象
重载

在第一个示例中,您试图传递一个
int
和一个
整数。
int
int
方法仅通过自动取消装箱第二个参数应用,而
对象
对象
方法仅通过自动装箱第一个参数应用。因此,重载不能在第一次传递时选择,并且因为两个方法都比另一个方法更具体(您需要查找最后一位),编译器不能在这两个方法之间进行选择

重载解析非常复杂,实际上我已经将其简化了很多(还有涉及var args的规则)。但是在实践中,您不需要学习所有这些规则-如果您需要告诉编译器要应用哪种方法,您可以始终包含一个或多个显式强制转换:

assertEquals((Integer) id, friend.getId());

在Java5之前,没有自动装箱或自动取消装箱。这意味着如果一个方法
foo
有一个类型为
Integer
的参数,那么下面的代码不会编译

foo(5);    // 5 needs to be autoboxed
bar(new Integer(5));    // The Integer needs to be unboxed
类似地,如果一个方法
bar
有一个类型为
int
的参数,那么它不会编译

foo(5);    // 5 needs to be autoboxed
bar(new Integer(5));    // The Integer needs to be unboxed
当引入自动装箱和自动取消装箱时,现有代码必须以与以前完全相同的方式继续工作。因此,当编译器决定调用哪个方法时,它首先只考虑不需要自动装箱或自动取消装箱的适用方法。只有当没有这样的方法时,编译器才会考虑需要自动装箱和/或自动解压的方法。 由于
getId
返回一个
整数
,因此当第一个参数也是
整数
时,可以调用
对象
对象
方法而无需自动装箱。但是,
int
int
方法只能通过自动取消绑定第二个参数来调用。因此,在第二个示例中,在第一次通过时选择了
对象
对象
重载

在第一个示例中,您试图传递一个
int
和一个
整数。
int
int
方法仅通过自动取消装箱第二个参数应用,而
对象
对象
方法仅通过自动装箱第一个参数应用。因此,重载不能在第一次传递时选择,并且因为两个方法都比另一个方法更具体(您需要查找最后一位),编译器不能在这两个方法之间进行选择

重载解析非常复杂,实际上我已经将其简化了很多(还有涉及var args的规则)。但是在实践中,您不需要学习所有这些规则-如果您需要告诉编译器要应用哪种方法,您可以始终包含一个或多个显式强制转换:

assertEquals((Integer) id, friend.getId());

您是否已将
Friend
id
定义为
int
Integer
?id是整数可以确认getId()的返回类型不是Integer int吗?是的,getId()的返回类型是整数您是否已将
Friend
id
定义为
int
Integer
?id是整数您是否可以确认getId()的返回类型是Integer而不是int?是的,getId()的返回类型是Integer