我刚刚发现了一个非常有趣的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和具有比简单的装箱转换较低的优先级。换句话说,如果有一个method1(Integer a, Integer b)
它会来之前method1(Integer... a)
在层次结构)
为什么会这样呢? 在15.12.2注释给出提示:
这保证了这是有效的在Java SE 5.0之前的Java编程语言中的任何调用并不认为是不明确引进的变量元数法,隐式装箱和/或拆箱的结果。
第二种方法获胜。 按照Java语言规范(PDF) ,
第一阶段(§15.12.2.2)执行重载而不允许拳击或取消装箱转换,或使用可变元数的方法调用的。
如果在此阶段被发现适用的方法,该方法获得; 没有进行进一步的搜索。 根据你的情况,它正好是第二种方法,因为第一个是可变的元数方法还需要拳。
我猜的一半,但像thinksteep说, Integer...
实际上是作为治疗Integer
数组,这意味着你的方法调用就必须做两个强制转换,使之符合第一种方法(拳击int
s到Integers
,和治疗您的参数列表作为一个数组,而不是简单的两种不同说法)。 然而, 不需要强制转换,使其符合第二种方法。
好吧,我可以看到几个人已经引述JLS更明确比我提供,我打字了这一点,同时。
呼叫将向方法1发(INT A,INT B)。 刚才检查字节码的这一点-这里Integer... a
实际上是一个Integer[] a
关于详细的转换检查这些赋值转换
可变参数具有最小的优先级 。 如果没有发现其他匹配方法则只有它得到called.It就像开关盒的默认情况。
文章来源: Which method is called? (Integer… a) vs. (int a, int b)