views:

340

answers:

4

Consider the following method signatures:

public fooMethod (Foo[] foos) { /*...*/ }

and

public fooMethod (Foo... foos) { /*...*/ }

Explanation: The former takes an array of Foo-objects as an argument - fooMethod(new Foo[]{..}) - while the latter takes an arbitrary amount of arguments of type Foo, and presents them as an array of Foo:s within the method - fooMethod(fooObject1, fooObject2, etc...).

Java throws a fit if both are defined, claiming that they are duplicate methods. I did some detective work, and found out that the first declaration really requires an explicit array of Foo objects, and that's the only way to call that method. The second way actually accepts both an arbitrary amount of Foo arguments AND also accepts an array of Foo objects.

So, the question is, since the latter method seems more flexible, are there any reasons to use the first example, or have I missed anything vital?

+1  A: 

The latter was introduced in Java 5 and existing libraries are gradually being reworked to support it. You might still use the former to stress that the method requires 2+ inputs, plus there are restrictions on where the ... can be used.

Garth Gilmour
Except it stresses nothing of the sort, and in fact allows 0 or 1 inputs (unless specified otherwise in documentation, in which case the variadic form is just as good).
Chris Jester-Young
+10  A: 

These methods are actually the same.

This feature is called varargs and it is a compiler feature. Behind the scenes is is translates to the former version.

There is a pitfall if you define a method that accepts Object... and you sent one parameter of type Object[]!

Shimi Bandiel
Java warns you about this, and asks you to either write (Object) array (for variadic mode) or (Object[]) array (for non-variadic mode). :-)
Chris Jester-Young
A: 

There are certainly no performance issues or things like that to consider, so it comes down to semantics.

Do you expect the caller of your method to have an array of Foo's ready at hand? Then use the Foo[] version. Use the varargs variant to emphasize the possibility of having a "bunch" of Foo's instead of an array.

A classical example for varargs ist the string-format (in C#, dunno how its called in Java):

string Format(string formatString, object... args)

Here you expect the args to be of different types, so having an array of arguments would be quite unusal, hence the varargs variant.

On the other hand in something like

string Join(string[] substrings, char concatenationCharacter)

using an Array is perfectly reasonable.

Also note that you can have multiple array-parameters and only one vararg parameter at the end of the paramater-list.

TToni
+2  A: 

I'd like to add to Shimi's explanation to add that another restriction of the varargs syntax is that the vararg must be the last declared parameter. So you can't do this:

void myMethod(String... values, int num);

This means that any given method can only have a single vararg parameter. In cases where you want to pass multiple arrays, you can use varargs for only one of them.

In practice, varargs are at their best when you are treating the args as an arbitrary number of distinct values, rather than as an array. Java5 maps them to an array simply because that was the most convenient thing to do.

A good example is String.format(). Here, the varargs are matched against the format placeholders in the first argument.

skaffman