使用原始类型和包装类的varargs重载时为什么会出现模糊错误? [英] Why ambiguous error when using varargs overloading with primitive type and wrapper class?

查看:158
本文介绍了使用原始类型和包装类的varargs重载时为什么会出现模糊错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



案例#1

  public class Test {

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

public void display(整数a){
System.out.println(2);
}

public static void main(String [] args){
new Test()。display(0);
}
}

输出为: 1



案例#2

 公共类测试{

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

public void display(整数... a){
System.out.println(2);
}

public static void main(String [] args){
new Test()。display(0);
}
}

编译错误

 方法display(int [])对于类型Test 
display(int)方法在严格的调用上下文中调用,而在宽松的调用上下文中调用 display(Integer)(因为需要自动装箱)。因此编译器根据JLS选择 display(int)方法。调用上下文在此处解释 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和第一个k m2
的变量arity参数类型是T1,...,Tk,对于所有i(1≤i≤k),类型Si对于参数ei
比Ti更具体。另外,如果m2有k + 1个参数,那么
第k + 1个变量arity参数类型m1是
k +第1个变量arity参数类型m2的子类型。


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


I do not understand why here in case 1, it is not giving compilation error, contrary in case 2 (varargs), it gives compilation error. Can anyone please elaborate what differences the compiler makes in these two cases? I went through many posts about it, but not able to understand it yet.

Case #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);
    }
}

The Output is: 1

Case #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);
    }
}

Compilation Error:

The method display(int[]) is ambiguous for the type Test

解决方案

In your first example the display(int) method is invoked in strict invocation context while display(Integer) is invoked in loose invocation context (since auto-boxing is required). Thus the compiler chooses the display(int) method according to JLS. Invocation contexts are explained here JLS 5.3. Invocation Contexts

In the second example both methods are invoked in loose invocation context thus the compiler needs to find the most specific method JLS 15.12.2.5 Choosing the Most Specific Method. Since int is not a subtype of Integer there is no most specific method and the compiler throws a compilation error.

You can find my explanation for a similar compilation error here Method overload ambiguity with Java 8 ternary conditional and unboxed primitives

The parts that apply to this case:

Identifying applicable methods is divided into 3 phases.

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.

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.

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

For the first example only the display(int) method is matched on the first phase thus it is chosen. For the second example both methods are matched on the 3rd phase thus the Choosing the Most Specific Method algorithm comes into play JLS 15.12.2.5 Choosing the Most Specific Method:

m2 is not generic, and m1 and m2 are applicable by variable arity invocation, and where the first k variable arity parameter types of m1 are S1, ..., Sk and the first k variable arity parameter types of m2 are T1, ..., Tk, the type Si is more specific than Ti for argument ei for all i (1 ≤ i ≤ k). Additionally, if m2 has k+1 parameters, then the k+1'th variable arity parameter type of m1 is a subtype of the k+1'th variable arity parameter type of m2.

As mentioned earlier there is no most specific method since int <: Integer does not satisfy.

这篇关于使用原始类型和包装类的varargs重载时为什么会出现模糊错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆