我刚刚发现了一个非常有趣的Java技巧:
void method1(Integer... a){
}
因此,您可以根据需要为此方法提供尽可能多的整数。
现在,如果我有类似的(重载)方法:
void method1(int a, int b){
}
执行以下行时运行哪个方法:
method1(1, 2);
好吧,通过使用不同的方法指令测试它,我很容易找到它,但是当我想到“重载”方法中的“规则”时,我必须确保每个重载方法必须相同,以便编译器确切地知道要使用哪一个。
在我看来,上面的代码不起作用,因为编译器应该混淆。但是,当我尝试它时,它可以工作。
那么..有没有人知道更多关于此的背景信息?
答案 0 :(得分:30)
要确定应调用哪个方法,编译器将按照JLS #5.3和JLS #15.12.2中的详细说明执行以下列表:
method1(int a, int b)
强> method1(Integer... a)
强> 在您的情况下,第一个点适用,并且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 情况的默认情况一样。