Java 使用var args重载方法-结合装箱和加宽

Java 使用var args重载方法-结合装箱和加宽,java,overloading,scjp,Java,Overloading,Scjp,当重载包含不匹配参数的方法时,JVM将始终使用具有比参数更宽的最小参数的方法 我用以下两个例子证实了上述情况: 加宽:字节加宽为int class ScjpTest{ static void go(int x){System.out.println("In Int");} static void go(long x){System.out.println("In long");} public static void main (String[] args){

当重载包含不匹配参数的方法时,JVM将始终使用具有比参数更宽的最小参数的方法

我用以下两个例子证实了上述情况:

加宽:字节加宽为int

class ScjpTest{

    static void go(int x){System.out.println("In Int");}
    static void go(long x){System.out.println("In long");}

    public static void main (String[] args){

        byte b = 5;

        go(b);

    }
}

装箱:整数装箱为整数

class ScjpTest{

    static void go(Integer x){System.out.println("In Int");}
    static void go(Long x){System.out.println("In Long");}

    public static void main (String[] args){

        int b = 5;

        go(b);

    }

}
上述两个示例都输出了“In Int”,这是正确的。但是,当情况涉及var args时,我感到困惑,如下面的示例所示

class ScjpTest{

    static void go(int... x){System.out.println("In Int");}
    static void go(long... x){System.out.println("In lInt");}

    public static void main (String[] args){

        byte b = 5;   //or even with:  int b = 5

        go(b);

    }

}
上述操作会产生以下错误:

ScjpTest.java:14: reference to go is ambiguous, both method go(int...) in ScjpTest and method go(long...) in ScjpTest match
                go(b);
                ^
1 error

为什么它不应用与前面示例中相同的规则?i、 e.将字节加宽为int,因为它是大于字节的最小值?

var args语法只是将数组作为参数传递的别名:

foo(int…arg)
等于
foo(int[]arg)


但数组不是分层的<代码>字符串[]不是
对象[]
的子类。完全相同的规则与方法参数相关。因此,当您传递
字节时,编译器无法区分接受
long[]
int[]
的两个重载方法。它实际上在Java 7中工作:对于varargs示例,它也返回“in int”。我想这只是以前版本中缺少的一个功能。我不知道您使用的是什么Java版本,但可能它也适用于Java6

然而,我必须说,即使是第一个示例(没有varargs),我也感到惊讶。我不知道原始加宽转换。
顺便说一下,如果改用Byte、Integer和Long,那么第一个和最后一个示例将失败,因为这些类型之间没有层次结构(除了它们都是Number的子类)。

正如AlexR指出的,var args就像一个数组。原语数组(如
byte[]short[]int[]long[]float[]double[])
似乎在内部编译为同一个类。这就是重载方法不明确的原因。但是以下代码完全有效:
static void go(int…x){System.out.println(“In int”);}
静态void go(Long…x){System.out.println(“In lInt”);}

这将成功编译(因为
int[]
Long[]
是不同的类型),并在int
中生成
输出

如果您正在准备SCJP,我强烈建议您阅读这本书。本书中的重载部分涵盖了混合装箱和var args的所有技巧。

错了。String[]是Object[]的子类。数组在Java中是协变的(但不是泛型)。请看我的答案:在旧的Java版本中,这实际上是一个错误,它不起作用。Zigy的示例在Java 7中确实起作用……但实际上,在这个示例中,所起的作用甚至不是数组继承,而是扩大了基元类型的转换。在Java 7上,您的最后一个示例工作得很好。