使用原始类型和包装类的varargs重载时为什么会出现模糊错误?

027*_*027 7 java primitive overloading variadic-functions wrapper

我不明白为什么在这里的情况1,它没有给出编译错误,相反在情况2(varargs),它给出了编译错误.任何人都可以详细说明编译器在这两种情况下的差异吗?我经历过很多关于它的帖子,但还不能理解它.

情况1

public class Test {

    public void display(int a) {
        System.out.println("1");
    }

    public void display(Integer a) {
        System.out.println("2");
    }

    public static void main(String[] args) {
        new Test().display(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

输出为: 1

案例#2

public class Test {

    public void display(int... a) {
        System.out.println("1");
    }

    public void display(Integer... a) {
        System.out.println("2");
    }

    public static void main(String[] args) {
        new Test().display(0);
    }
}
Run Code Online (Sandbox Code Playgroud)

编译错误:

The method display(int[]) is ambiguous for the type Test
Run Code Online (Sandbox Code Playgroud)

med*_*088 5

在第一个示例中,该display(int)方法在严格的调用上下文display(Integer)中调用,而在松散的调用上下文中调用(因为需要自动装箱).因此编译器display(int)根据JLS 选择方法.调用上下文在JLS 5.3中进行了解释.调用上下文

在第二个示例中,两个方法都在松散调用上下文中调用,因此编译器需要找到最具体的方法JLS 15.12.2.5选择最具体的方法.由于int不是Integer的子类型,因此没有最具体的方法,编译器会抛出编译错误.

你可以在这里找到我对类似编译错误的解释.使用Java 8三元条件和非盒装原语的方法重载歧义

适用于此案例的部分:

确定适用的方法分为3个阶段.

第一阶段(§15.12.2.2)执行重载解析而不允许装箱或拆箱转换,或使用变量arity方法调用.如果在此阶段没有找到适用的方法,则处理继续到第二阶段.

第二阶段(§15.12.2.3)执行重载解析,同时允许装箱和拆箱,但仍然排除使用变量arity方法调用.如果在此阶段没有找到适用的方法,则处理继续到第三阶段.

第三阶段(§15.12.2.4)允许重载与变量arity方法,装箱和拆箱相结合 .

对于第一个示例,仅在display(int)第一阶段匹配该方法,因此选择该方法.对于第二个示例,两个方法在第三阶段匹配,因此选择最具体方法算法发挥作用JLS 15.12.2.5选择最具体的方法:

m2不是通用的,m1和m2适用于变量arity调用,并且m1的前k个变量arity参数类型是S1,...,Sk和m2的前k个变量arity参数类型是T1,..对于所有i(1≤i≤k),对于参数ei,Si类型比Ti更具体.另外,如果m2具有k + 1个参数,则m1的第k + 1个可变参数类型是第m + 1个可变参数类型m2的子类型.

如前所述,由于int <:Integer不满足,因此没有最具体的方法.