请考虑以下示例代码:
public class TestClass {
public void doSth(String str, String l, Object... objects) {
System.out.println("A");
}
public void doSth(String str, Object... objects) {
System.out.println("B");
}
}
当我现在致电new TestClass().doSth("foo", "bar")
时,我得到了预期的结果A
。但是,如果我通过将参数l
变为基本类型来更改第一个方法的方法签名:
public class TestClass {
public void doSth(String str, long l, Object... objects) {
System.out.println("A");
}
public void doSth(String str, Object... objects) {
System.out.println("B");
}
}
调用new TestClass().doSth("foo", 2L)
将产生reference to call ambiguous
编译时错误。
我现在已经考虑了一段时间并且还咨询了this stackoverflow question,但我无法理解为什么会发生这种情况。在我看来,doSth("foo", 2L)
更具体于doSth(String string, long l, Object... obj)
签名,并且应该允许编译器得出这个结论。
答案 0 :(得分:5)
在这种情况下,自动拳击会让你感到悲伤。具有讽刺意味的是,在此之前你是正确的 - “长”版本很容易被选中。
基本上编译器知道它可以从你的值创建一个Long,当然,它是一个Object。所以它仍然很混乱,因为可以使用long版本或Long版本。这个比那个好吗?也许,但这是一个非常好的路线。
答案 1 :(得分:1)
在这种状态下,我只能报告我的观察结果,而不是像Java那样的确切论证,就像它一样。
首先,将方法更改为
void doSth(long l) {...}
void doSth(Object o) {...}
解决问题,即doSth(2L);
将产生预期结果。
更进一步,将方法参数更改为varargs
void doSth(long... ls) {...}
void doSth(Object... os) {...}
与调用doSth(2l);
一起产生与OP报告的相同的编译错误。
我在这个阶段的建议是将参数包含在一个数组中,与Autoboxing一起导致破坏。我对JLS的了解并不足以解释这一点。