【问题标题】:Overloading methods with var-args - combined with boxing and widening使用 var-args 重载方法 - 结合装箱和加宽
【发布时间】:2011-08-14 12:54:29
【问题描述】:

当重载包含不匹配参数的方法时,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,因为它是大于字节的最小的?

【问题讨论】:

  • 在 Java 7 上,您的最后一个示例运行良好。

标签: java overloading scjp


【解决方案1】:

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

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

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

【讨论】:

  • 错了。 String[] 是 Object[] 的子类。数组在 Java 中是协变的(但不是泛型)。请参阅我的回答:它实际上是旧 Java 版本中的一个错误,它不起作用。 ziggy 的示例在 Java 7 中确实有效。
  • ...但实际上在这个例子中起作用的甚至不是数组继承,而是扩大原始类型的转换。
【解决方案2】:

正如 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。本书中的重载部分涵盖了混合装箱和可变参数的所有技巧。

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多