简体   繁体   English

使用变量参数重载的方法

[英]Method overloading with variable argument

I think this would be a stupid question a little bit, but I can not sure why it is. 我认为这会是一个愚蠢的问题,但我不知道为什么会这样。

code; 码;

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));
    }
}

results I expected; 结果我期待;

4.0
this is variant args//30
this is variant args//60

actual results in console: 控制台中的实际结果:

 4.0 30.0 this is variant args//60 

I can not sure why results of sum(10, 20) 30.0, not 30 of variable argument. 我不能确定为什么sum(10, 20) 30.0的结果,而不是变量参数的30。

This is because the compiler always makes the choice to use the most specific method. 这是因为编译器总是选择使用最具体的方法。

Since your second invocation has two arguments, and an int can be converted to a double without loss of precision (see JLS, section 5.1.2 ), the compiler elects to call your two-argument method. 由于您的第二次调用有两个参数,并且int可以转换为double而不会丢失精度(请参阅JLS,第5.1.2节 ),编译器会选择调用您的双参数方法。

An IDE will warn you here about the implicit int to double conversion. IDE会在这里警告你有关double转换的隐式int


edit: as @OlegEterkhin mentions in comments, see JLS, section 15.2.2 for the process used by the compiler to select which method will be used. 编辑:正如@OlegEterkhin在注释中提到的,请参阅JLS,第15.2.2节 ,了解编译器用于选择将使用哪种方法的过程。

And no, this won't work: 不,这不起作用:

int x = sum(10, 20);

The answer is in JLS section 15.12.2 . 答案在JLS第15.12.2节中 Basically, the compiler tries to find any applicable method without having to expand varargs, only using varargs if it has to: 基本上,编译器试图找到任何适用的方法, 不必扩展varargs,只有使用varargs,如果它必须:

The remainder of the process is split into three phases, to ensure compatibility with versions of the Java programming language prior to Java SE 5.0. 该过程的其余部分分为三个阶段,以确保与Java SE 5.0之前的Java编程语言版本兼容。 The phases are: 阶段是:

  • The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. 第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用。 If no applicable method is found during this phase then processing continues to the second phase. 如果在此阶段没有找到适用的方法,则处理继续到第二阶段。 [...] [...]

  • The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. 第二阶段(§15.12.2.3)执行重载解析,同时允许装箱和拆箱,但仍然排除使用变量arity方法调用。 If no applicable method is found during this phase then processing continues to the third phase. 如果在此阶段没有找到适用的方法,则处理继续到第三阶段。 [...] [...]

  • The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing. 第三阶段(§15.12.2.4)允许重载与变量arity方法,装箱和拆箱相结合。

In this case, the first phase does find a match, as sum(double, double) is applicable for the call sum(10, 20) due to the implicit conversion from int to double . 在这种情况下,第一阶段确实找到匹配,因为sum(double, double)适用于调用sum(10, 20)因为从intdouble的隐式转换。

In the line: 在线:

System.out.println(sum(10, 20));

The number of the parameters match the signature of sum(double a, double b) and it's the most accurate method and it's the one chosen by the compiler . 参数的数量sum(double a, double b)的签名匹配sum(double a, double b) ,它是准确的方法,也是编译器选择的方法。

See 15.12.2. 15.12.2。 Compile-Time Step 2: Determine Method Signature for details. 编译时步骤2:确定方法签名以获取详细信息。

Based upon this post Varargs in method overloading in Java 基于这篇文章Varargs在Java中的方法重载

There are some rules that are followed when selecting which overloaded method to select, when Boxing, Widening, and Var-args are combined: - 选择要选择的重载方法,组合Boxing,Widening和Var-args时,遵循一些规则: -

Primitive widening uses the smallest method argument possible
Wrapper type cannot be widened to another Wrapper type
You can Box from int to Integer and widen to Object but no to Long
Widening beats Boxing, Boxing beats Var-args.
You can Box and then Widen (An int can become Object via Integer)
You cannot Widen and then Box (An int cannot become Long)
You cannot combine var-args, with either widening or boxing

Type inference has a sort of priority over the varargs. 类型推断具有优于varargs的优先级。 Since you call a method with 2 arguments, it tries to find a match with 2 arguments (even with type inference) before searching for varargs methods (even with the right type). 由于您使用2个参数调用方法,因此在搜索varargs方法之前,它会尝试查找与2个参数匹配(即使使用类型推断)(即使使用正确的类型)。

This behavior is defined in the specification . 此行为在规范中定义。 "Variable arity methods, boxing, and unboxing " are handled in the third phase of method signature resolution, after first trying to match the signature without using variable arity methods. 在第一次尝试匹配签名而不使用变量arity方法之后,在方法签名解析的第三阶段处理“变量方法,装箱和取消装箱”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM