重载varargs数组,选择方法

man*_*vel 11 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";}
Run Code Online (Sandbox Code Playgroud)

现在当我使用它们时:

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

我正进入(状态

Integer[] args
Object args
Run Code Online (Sandbox Code Playgroud)

这是一个问题:为什么我们有两种不同的输出?
Integer[]可以隐式地转换为两者Object,和Object[].

小智 4

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

你打电话时

System.out.println(foo(i));//Object[]... vs Integer[]...
Run Code Online (Sandbox Code Playgroud)

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

因为在运行时,JVM 将调用委托给带Integer[][]参数的方法,而不是带Object[][] varags指定的参数的方法。因为使用 Integer[][] 而不是 Object[][] 调用方法会更具体。


在后面的语句中,当你调用

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

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

再次使用 varags,参数的类型将是 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";
    }
Run Code Online (Sandbox Code Playgroud)

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

因此,更准确地说,根据数组类型中的 JLS 子类型

  • 如果 S 和 T 都是引用类型,则 S[] > T[] 当且仅当 S > T。
  • 对象 > 对象[]

这意味着将对具有 Integer[][] 而不是 Object[][] 的方法进行 Integer[] 调用。Integer[] 的调用将调用 Object[] 而不是 Integer[][]。

请参阅此处选择最具体的方法。