带变量参数的java方法重载
我认为这是一个有点愚蠢的问题,但我不知道为什么
代码
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));
}
}
我期望的结果
4.0
this is variant args//30
this is variant args//60
控制台中的实际结果:
4.0 30.0 this is variant args//60
我不知道为什么sum(10, 20)
30.0的结果,而不是变量参数的30
# 1 楼答案
答案在JLS section 15.12.2中。基本上,编译器试图找到任何适用的方法,而不必展开varargs,只有在必须的情况下才使用varargs:
在这种情况下,第一阶段确实找到了匹配项,因为
sum(double, double)
由于从int
到double
的隐式转换而适用于调用sum(10, 20)
# 2 楼答案
这是因为编译器总是选择使用最具体的方法
由于第二次调用有两个参数,并且
int
可以转换为double
而不会损失精度(请参见JLS, section 5.1.2),编译器选择调用双参数方法IDE会在这里警告您关于
int
到double
的隐式转换编辑:正如@OlegEterkhin在评论中提到的,请参见JLS, section 15.2.2,了解编译器选择将使用哪个方法的过程
不,这行不通:
# 3 楼答案
这种行为在specification中定义。“变量算术方法、装箱和拆箱”在方法签名解析的第三阶段处理,首先尝试在不使用变量算术方法的情况下匹配签名
# 4 楼答案
类型推断比varargs具有某种优先级。由于您使用两个参数调用一个方法,因此在搜索varargs方法(即使使用正确的类型)之前,它会尝试使用两个参数查找匹配项(即使使用类型推断)
# 5 楼答案
在这一行:
参数的个数与
sum(double a, double b)
的签名匹配,这是最准确的方法,也是编译器选择的方法详见15.12.2. Compile-Time Step 2: Determine Method Signature
# 6 楼答案
基于这篇文章Varargs in method overloading in Java
选择要选择的重载方法、组合装箱、加宽和变量参数时,需要遵循一些规则:-