13

我想知道为什么 Java 中不允许重载Foo(Object[] args)with Foo(Object... args),尽管它们以不同的方式使用?

Foo(Object[] args){}

像这样使用:

Foo(new Object[]{new Object(), new Object()});

而另一种形式:

Foo(Object... args){}

像这样使用:

Foo(new Object(), new Object());

这背后有什么原因吗?

4

2 回答 2

25

这个15.12.2.5 选择最具体的方法讲到这个,但它相当复杂。例如在 Foo(Number... ints) 和 Foo(Integer... ints) 之间进行选择

为了向后兼容,这些实际上是同一件事。

public Foo(Object... args){} // syntactic sugar for Foo(Object[] args){}

// calls the varargs method.
Foo(new Object[]{new Object(), new Object()});

例如,您可以将 main() 定义为

public static void main(String... args) {

使它们不同的一种方法是在可变参数之前采用一个参数

public Foo(Object o, Object... os){} 

public Foo(Object[] os) {}

Foo(new Object(), new Object()); // calls the first.

Foo(new Object[]{new Object(), new Object()}); // calls the second.

它们并不完全相同。细微的区别在于,虽然您可以将数组传递给可变参数,但您不能将数组参数视为可变参数。

public Foo(Object... os){} 

public Bar(Object[] os) {}

Foo(new Object[]{new Object(), new Object()}); // compiles fine.

Bar(new Object(), new Object()); // Fails to compile.

此外,可变参数必须是最后一个参数。

public Foo(Object... os, int i){} // fails to compile.

public Bar(Object[] os, int i) {} // compiles ok.
于 2012-01-12T16:18:05.420 回答
3

对这个问题最直接的回答是,同时拥有这两个声明会在方法查找逻辑中产生歧义。如果您在同一个类中声明了两者,那么在调用时将无法确定您想要哪种方法:

Object[] a = new Object[10];
Foo(a); // array or vararg?

Java 要求每个方法调用始终有一个最具体的方法。对于为什么,请参阅彼得的回答。

于 2012-01-12T17:30:53.883 回答