5

当重载包含不匹配参数的方法时,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 装箱为 Integer

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,因为它是大于字节的最小的?

4

3 回答 3

5

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

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

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

于 2011-08-14T13:05:52.573 回答
1

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

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

于 2011-08-14T13:39:25.983 回答
1

正如 AlexR 所指出的,var-args 就像一个数组。基元数组(例如byte[] short[] int[] long[] float[] double[]似乎在内部编译为同一个类。这就是您的重载方法不明确的原因。但是以下代码完全有效: 这编译成功(因为和是不同的类型),并产生输出。 如果你'正在为 SCJP 做准备,我强烈建议您阅读SCJP Sun Certified Programmer for Java 6 Exam 310-065这本书。本书中的重载部分涵盖了混合拳击和 var-args 的所有技巧。
static void go(int... x){System.out.println("In Int");}
static void go(Long... x){System.out.println("In lInt");}

int[]Long[]In Int

于 2011-08-14T13:40:58.687 回答