叫哪种方法? (整数... a)与(int a,int b)

时间:2012-08-03 21:29:50

标签: java methods overloading variadic-functions

我刚刚发现了一个非常有趣的Java技巧:

void method1(Integer... a){
}

因此,您可以根据需要为此方法提供尽可能多的整数。

现在,如果我有类似的(重载)方法:

void method1(int a, int b){

}

执行以下行时运行哪个方法:

method1(1, 2);

好吧,通过使用不同的方法指令测试它,我很容易找到它,但是当我想到“重载”方法中的“规则”时,我必须确保每个重载方法必须相同,以便编译器确切地知道要使用哪一个。

在我看来,上面的代码不起作用,因为编译器应该混淆。但是,当我尝试它时,它可以工作。

那么..有没有人知道更多关于此的背景信息?

5 个答案:

答案 0 :(得分:30)

要确定应调用哪个方法,编译器将按照JLS #5.3JLS #15.12.2中的详细说明执行以下列表:

  • 身份转换(第5.1.1节) => method1(int a, int b)
  • 扩大原始转换(第5.1.2节)
  • 扩大参考转换(第5.1.5节)
  • 拳击转换(§5.1.7),可选地后跟加宽参考转换 ==> method1(Integer... a)
  • 一个拆箱转换(第5.1.8节),可选地后跟一个加宽的基元转换。

在您的情况下,第一个点适用,并且method1(int, int)被调用。

(更确切地说,你的方法使用varags并且优先级低于简单的拳击转换。换句话说,如果有method1(Integer a, Integer b),它将会出现在method1(Integer... a)之前层次结构)

为什么会这样? 15.12.2中的评论给出了一个提示:

  

这保证了在Java SE 5.0之前在Java编程语言中有效的任何调用都不会因为引入变量arity方法,隐式装箱和/或取消装箱而被认为是不明确的。

答案 1 :(得分:4)

第二种方法获胜。根据{{​​3}},

  

第一阶段(§15.12.2.2)在不允许的情况下执行重载决策   装箱或拆箱转换,或使用变量arity方法调用。

如果在此阶段找到适用的方法,则该方法获胜;没有进一步搜索。在你的情况下,它恰好是第二种方法,因为第一种方法是一种变量arity方法,也需要装箱。

答案 2 :(得分:2)

将调用method1(int a,int b)。 只需检查字节代码 - 此处Integer... a实际上是Integer[] a 要进行详细转换,请检查这些assignment conversion

答案 3 :(得分:2)

我猜不到,但是像thinksteep所说,Integer...实际上被视为Integer数组,这意味着你的方法调用必须做两次强制才能使它与第一种方法匹配(将int装入Integers,并将参数列表视为数组,而不仅仅是两个不同的参数。然而,没有强制要求使其与第二种方法相匹配。

好的,我可以看到其他几个人已经引用了比我提供的更具特异性的JLS,而我正在输入它。

答案 4 :(得分:1)

varargs具有最低优先级。如果找不到其他匹配的方法,则只调用它。它就像 SWITCH 情况的默认情况一样。