public class Demo {
public static String doit(int x,int y)
{
return"a";
}
public static String doit(int ...val)
{
return "b";
}
public static void main(String args[])
{
System.out.println(doit(4,5));
}
}
我怀疑为什么compilier没有显示任何错误,因为doit(4,5)导致歧义
当我编写代码时,我得到广告输出而不是为什么?
答案 0 :(得分:3)
Java语言规范定义应该调用第一个方法(“a”)(而不是“b”)。
请参阅http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.12.2
为了保持与以前Java版本的向后兼容性(在引入varargs之前),编译器将始终选择具有确切数量的参数的方法,即使varargs方法也存在。
至于你是否收到警告,编译器可以自由添加其他警告,并且可能会有一些警告这种情况,我猜你的情况没有(至少没有你的设置)< / p>
答案 1 :(得分:1)
JLS指定用于解决歧义的规则。简化版本是编译器首先尝试将调用与可用重载匹配,将varadic参数视为简单数组。如果成功,那就是它。如果失败,它会再次尝试将最后一个参数视为varadic。
在这种情况下,第一轮匹配给出了明确的匹配。
如果您感兴趣,可以在Section 15.12.2中给出用于确定应使用哪种方法的JLS规则。 (警告:实际的JLS规则比上面的简化版本更复杂,并且使用的语言/符号非常技术性。)
答案 2 :(得分:1)
public static String doit(int ...val)
{
return "b";
}
将被编译器视为
public static String doit(int[] val)
{
return "b";
}
当传递doit(2,2)时,将调用第一个方法,因为参数不是数组。
当传递doit(2,2,2)时,参数将转换为数组并传递给第二个方法。
将第一种方法改为
public static String doit(int x,int ...y)
{
return"a";
}
调用doid(2,2),它会说错误
doit(int, int[]) is ambigious.
答案 3 :(得分:0)
编译器尝试匹配最具体的替代方案。然而,可以认为它应该导致模糊错误。
来自Java语言规范 15.12.2.5
如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符。 Java编程语言使用选择最具体方法的规则。
答案 4 :(得分:0)
编译器总是尝试解析对它可以找到的最具体的函数调用的调用,在这种情况下是方法A.这不是一个真正的错误但如果你认为它不是编译器错误,它在规范中。一旦自动装箱发挥作用,你应该看到你可以从中获得的疯狂东西。
答案 5 :(得分:0)
这是他们在执行varargs规范时所做的妥协(很难知道哪些被调用)。因此,建议不要使varargs方法过载。引自their site:
一般来说,你不应该重载varargs方法,否则程序员很难弄清楚调用哪些重载。