Java重载:引用不明确的

时间:2016-05-19 20:09:59

标签: java overloading primitive jls

请考虑以下示例代码:

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)签名,并且应该允许编译器得出这个结论。

2 个答案:

答案 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的了解并不足以解释这一点。