首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么在使用varargs重载原始类型和包装类时出现不明确的错误?

为什么在使用varargs重载原始类型和包装类时出现不明确的错误?
EN

Stack Overflow用户
提问于 2016-04-03 10:51:03
回答 2查看 686关注 0票数 8

我不明白为什么在第1种情况下,它没有给出编译错误,相反,在案例2 (varargs)中,它给出了编译错误。有谁能详细说明编译器在这两种情况下的区别吗?我看了很多关于它的帖子,但还不能理解。

案件1

代码语言:javascript
运行
复制
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);
    }
}

输出是:1

案例2

代码语言:javascript
运行
复制
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);
    }
}

编译错误

代码语言:javascript
运行
复制
The method display(int[]) is ambiguous for the type Test
EN

回答 2

Stack Overflow用户

发布于 2016-04-03 11:03:31

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

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

您可以在这里找到我对类似编译错误的解释,Java 8三值条件和未装箱原语的过载歧义

应用于本例的部分:

确定适用方法分为三个阶段。 第一阶段(§15.12.2.2)执行重载解析,而不允许装箱或取消装箱转换,也不允许使用变量方法调用。如果在此阶段没有找到适用的方法,则处理将继续到第二阶段。 第二阶段(§15.12.2.3)执行过载解析,同时允许装箱和取消装箱,,但仍然排除使用可变的方法调用。如果在此阶段没有找到适用的方法,则处理将继续到第三阶段。 第三阶段(§15.12.2.4)允许将重载与变量方法、装箱和取消装箱相结合。

对于第一个示例,第一阶段只匹配display(int)方法,因此选择了该方法。在第二个例子中,这两种方法在第三阶段是匹配的,因此选择最具体的方法算法将进入JLS 15.12.2.5选择最具体的方法

m2不是泛型的,m1和m2适用于变量性调用,当m1的第一个k变量参数类型为S1、.、Sk和m2的第一个k变量参数类型为T1、.、Tk时,对于所有i (1≤i≤k),Si型比Ti更特殊。另外,如果m2有k+1参数,则m1的k+1'th变量参数类型是m2的k+1‘变量参数类型的一个子类型。

如前所述,没有最具体的方法,因为int <:整数不满足。

票数 6
EN

Stack Overflow用户

发布于 2016-04-03 11:14:56

JavaVersion1.5之后,引入了一个很酷的特性,名为autoboxing,它使编译器能够将原语类型转换为包装器类型。因此,在编译过程中,这两种方法的工作方式是相同的。

代码语言:javascript
运行
复制
    public void display(int... a) {
        System.out.println("1");
    }

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

由于autoboxing编译期间执行,所以这两个函数将被视为一个相同的方法。因此,在Java中重载方法时,请注意自动装箱

你在这里发现的更多..。

方法重载的最佳实践

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36384527

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档