public class Test
{
public static void printValue(int i, int j, int k)
{
System.out.println("int");
}
public static void printValue(byte...b)
{
System.out.println("long");
}
public static void main(String... args)
{
byte b = 9;
printValue(b,b,b);
}
}
上面的代码的输出是“int”。 但它应该是“长”,因为字节类型参数的功能已经存在。 但这里的程序正在推动字节值来诠释,但它不应该是这样的。
请某人能澄清这到底是怎么回事呢?
可变参数的方法总是会通过在重载方法情况下,编译被选择的最后一个。 一个促进byte
到int
(扩大变换)将在采用一个无功arg参数的方法是优选的。
这背后的原因是语言需要向后兼容。 较早的功能将优先于较新的功能。 理解一个简单的方法是什么JLS说,关于可变参数是扩大将打拳击和拳击将击败VAR-ARGS。
JLS 15.12.2是规范的相关位看这里。 特别是 - 重点煤矿:
该工艺的其余部分被分为三个阶段,以确保与Java SE 5.0之前,Java编程语言的版本兼容。 该阶段是:
第一阶段(§15.12.2.2)执行重载而不允许拳击或取消装箱转换,或使用可变元数的方法调用的。 如果在此阶段没有发现适用方法然后处理继续到第二阶段。
这保证了这是有效的在Java SE 5.0之前的Java编程语言中的任何调用并不认为是不明确引进的变量元数法,隐式装箱和/或拆箱的结果。 然而,可变元数法(§8.4.1)的声明可以改变选择用于给定方法的方法调用表达的方法中,因为可变的arity方法作为在第一阶段的固定元数的方法进行处理。 例如,声明m(Object...)
其中已经声明一个类m(Object)
导致m(Object)
不再被选择用于某些调用表达式(如m(null)
如m(Object[])
是更具体的。
第二阶段(§15.12.2.3)执行重载解析,同时允许装箱和拆箱,但仍排除使用可变元数的方法调用的。 如果在此阶段没有发现适用方法然后处理继续到第三阶段。
这确保了一种方法,通过从未可变元数的方法调用选择,如果它是适用通过固定元数的方法调用。
第三阶段(§15.12.2.4)允许重载具有可变元数的方法,拳击,和取消装箱组合。
在你的情况下,第一阶段找到一个匹配,而无需使用可变参数数量的方法调用或打拳,因此这就是结果。 正如规范所指出的,这基本上是为了向后兼容。
文章来源: Why does type-promotion take precedence over varargs for overloaded methods