为什么类型提升优先于重载方法的可变参数

Why does type-promotion take precedence over varargs for overloaded methods

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"。但它应该是 "long" 因为字节类型参数函数已经存在。但是这里程序将字节值提升为int,但不应该是这样。

有人可以澄清这里发生了什么吗?

JLS 15.12.2 是此处要查看的规范的相关部分。特别是 - 强调我的:

The remainder of the process is split into three phases, to ensure compatibility with versions of the Java programming language prior to Java SE 5.0. The phases are:

  • The first phase (§15.12.2.2) performs overload resolution without permitting boxing or unboxing conversion, or the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the second phase.

    This guarantees that any calls that were valid in the Java programming language before Java SE 5.0 are not considered ambiguous as the result of the introduction of variable arity methods, implicit boxing and/or unboxing. However, the declaration of a variable arity method (§8.4.1) can change the method chosen for a given method method invocation expression, because a variable arity method is treated as a fixed arity method in the first phase. For example, declaring m(Object...) in a class which already declares m(Object) causes m(Object) to no longer be chosen for some invocation expressions (such as m(null)), as m(Object[]) is more specific.

  • The second phase (§15.12.2.3) performs overload resolution while allowing boxing and unboxing, but still precludes the use of variable arity method invocation. If no applicable method is found during this phase then processing continues to the third phase.

    This ensures that a method is never chosen through variable arity method invocation if it is applicable through fixed arity method invocation.

  • The third phase (§15.12.2.4) allows overloading to be combined with variable arity methods, boxing, and unboxing.

在您的例子中,第一阶段找到匹配项而不使用可变元数方法调用或装箱,因此这就是结果。如规范中所述,这基本上是为了向后兼容。

在重载方法的情况下,可变参数方法将始终是编译器选择的最后一个方法。将 byte 提升为 int(扩大转换)将优于采用 var-arg 参数的方法。

这背后的原因是语言需要向后兼容。较旧的功能将优先于较新的功能。理解 JLS 关于可变参数的一个简单方法是,加宽将击败装箱,而装箱将击败 var-args。