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

时间:2011-08-14 12:54:29

标签: 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){

        byte b = 5;

        go(b);

    }

}

拳击:int盒装到整数

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

为什么它不应用与前面示例中相同的规则?即将字节扩展为int,因为它是大于字节的最小值?

3 个答案:

答案 0 :(得分:5)

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

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

但是数组不是分层的。 String[]不是Object[]的子类。完全相同的规则与方法参数相关。因此,当您传递long[]时,编译器无法区分接受int[]byte的2个重载方法。

答案 1 :(得分:1)

它实际上适用于Java 7:它也为varargs示例返回“In Int”。我想这只是以前版本中缺少的功能。我不知道你正在使用什么Java版本,但也许它也适用于Java 6。

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

答案 2 :(得分:1)

正如AlexR指出的那样,var-args就像一个数组。基元的数组(例如byte[] short[] int[] long[] float[] double[])似乎在内部编译到同一个类。这就是为什么你的重载方法是模糊的。但是下面的代码是完全有效的:
    static void go(int... x){System.out.println("In Int");}
static void go(Long... x){System.out.println("In lInt");}

这成功编译(因为int[]Long[]是不同的类型),并生成输出In Int
如果您正在为SCJP做准备,我强烈建议您阅读本书SCJP Sun Certified Programmer for Java 6 Exam 310-065。本书中的重载部分涵盖了混合装箱和var-args的所有技巧。