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

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

void method1(Integer... a){ } 

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

现在,如果我有一个类似的(重载)方法,如下所示:

 void method1(int a, int b){ } 

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

 method1(1, 2); 

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

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

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

要确定应该调用哪个方法,编译器将按照以下列表进行操作,如JLS#5.3和JLS#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并且优先级低于简单的装箱转换。换句话说,如果有一个方法1 method1(Integer a, Integer b)它将在method1(Integer... a)出现层次结构)

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

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

第二种方法获胜。 根据Java语言规范(pdf) ,

第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用。

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

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

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

将调用method1(int a,int b)。 刚刚检查了字节代码 – 这里Integer... a实际上是一个Integer[] a对于详细的转换检查这些赋值转换

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