rap*_*pot 4 java variadic-functions
我认为这会是一个愚蠢的问题,但我不知道为什么会这样.
码;
public class OverloadingTest {
public static int sum(int ...a){
int sum=0;
for(int i : a){
sum += i;
}
System.out.print("this is variant args//");
return sum;
}
public static double sum(double a, double b) {
return a + b;
}
public static void main(String[] args) {
System.out.println(sum(1.5, 2.5));
System.out.println(sum(10, 20));
System.out.println(sum(10, 20,30));
}
}
Run Code Online (Sandbox Code Playgroud)
结果我期待;
4.0
this is variant args//30
this is variant args//60
Run Code Online (Sandbox Code Playgroud)
控制台中的实际结果:
Run Code Online (Sandbox Code Playgroud)4.0 30.0 this is variant args//60
我不能确定为什么sum(10, 20)30.0的结果,而不是变量参数的30.
这是因为编译器总是选择使用最具体的方法.
由于您的第二次调用有两个参数,并且int可以转换为double不失精度(参见JLS,第5.1.2节),编译器会选择调用您的双参数方法.
一个IDE将在这里提醒你有关隐int到double转换.
编辑:正如@OlegEterkhin在注释中提到的,请参阅JLS,第15.2.2节,了解编译器用于选择将使用哪种方法的过程.
不,这不起作用:
int x = sum(10, 20);
Run Code Online (Sandbox Code Playgroud)
答案在JLS第15.12.2节中.基本上,编译器试图找到任何适用的方法,而不必扩展varargs,只有使用varargs,如果它必须:
该过程的其余部分分为三个阶段,以确保与Java SE 5.0之前的Java编程语言版本兼容.阶段是:
第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用.如果在此阶段没有找到适用的方法,则处理继续到第二阶段.[...]
第二阶段(§15.12.2.3)执行重载解析,同时允许装箱和拆箱,但仍然排除使用变量arity方法调用.如果在此阶段没有找到适用的方法,则处理继续到第三阶段.[...]
第三阶段(§15.12.2.4)允许重载与变量arity方法,装箱和拆箱相结合.
在这种情况下,第一阶段确实找到匹配,因为从隐式转换到,sum(double, double)所以适用于调用.sum(10, 20)intdouble