叫哪种方法? (整数… 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情况的默认情况一样。