重载varargs数组,选择方法

时间:2015-11-01 20:52:17

标签: java overloading

我有两个重载方法:foobar

//Object[]... vs Integer[]...
public static String foo(Object[]... args)  { return "Object[] args"; }
public static String foo(Integer[]... args) { return "Integer[] args";}

//Object... vs Integer[]...
public static String bar(Object... args) {return "Object args";}
public static String bar(Integer[]... args) {return "Integer[] args";}

现在当我使用它们时:

Integer[] i = { 5 };
System.out.println(foo(i));//Object[]... vs Integer[]...
System.out.println(bar(i));//Object... vs Integer[]...

我正在

Integer[] args
Object args

这是一个问题:为什么我们有两种不同的输出?
Integer[] {}可以隐式投放ObjectObject[]

2 个答案:

答案 0 :(得分:3)

在第一种情况下,args的类型实际上是Integer [] [],即你的数组被varargs装入另一个数组。编译器选择Integer []版本,因为它是最具体的类型。

在第二种情况下,args == i并且是一个Integer []。在这种情况下,编译器必须选择将它包装在一个新数组中以调用Integer [] ...版本,或者只是将Integer []转换为Object []。它选择了第二个,因为这是规则。

故事的寓意是:不要超载varargs方法 - 这让人感到困惑。

答案 1 :(得分:3)

这基本上是编译器决定在所有方法中调用最具体的方法。

致电时

System.out.println(foo(i));//Object[]... vs Integer[]...

它会调用foo(Integer[]... args)

因为在运行时,JVM使用Integer[][]参数委托对方法的调用,而使用varags指定的不使用Object[][] param 方法。因为使用Integer [] []而不是Object [] []。

调用方法会更具体

在后面的陈述中,当你打电话

System.out.println(bar(i));//Object... vs Integer[]...

它将转到bar(Object... args)

再次使用varags,param的类型将是Object []而不是Object [] []。编译器将再次调用最具体的方法,即具有Object... args的方法。

如果您通过删除varags来更改方法签名:

   //Object... vs Integer[]...
    public static String bar(Object args) {

        return "Object args";
    }

    public static String bar(Integer[] args) {
        return "Integer[] args";
    }

然后您会注意到它将调用bar(Integer[] args),因为它更具体于方法调用。

因此,根据JLS Subtyping among Array Types更准确,

  • 如果S和T都是参考类型,那么S []> T [] iff S>吨。
  • 对象>对象[]

这意味着将对具有Integer [] []而不是Object [] []的方法调用Integer []。 其中Integer []的调用将发送到Object []而不是Integer [] []。

请参阅here以选择最具体的方法。