views:

94

answers:

3

I have question: what is the difference between these two declarations?

 public static void printMax(double... numbers) { ... }

 public static void printmax(double numbers[])  { ... }

Is double... numbers the same as double numbers[]?

+2  A: 

The major difference is that in the first case, you could call printMax with multiple arguments:

printMax(3.0, 4.0, 5.0)

whereas in the second case it would only accept a single argument (an array of double).

Within the method body, numbers will be accessed as an array in both cases.

One thing to keep in mind is that in the first case, you can still pass a single array of double even though the varargs notation is used.

danben
+1  A: 

Not exactly - double... means variable argument list - all the arguments passed at this point will be packed together as one array.

There can be only one vararg parameter in a method and it has to be the last in its prototype for obvious reasons. It will however be available in the method as an array, so in this particular case there is not much difference.

Bozhidar Batsov
+4  A: 

On varargs

The Type... construct in method parameter declaration is commonly what is called varargs. In JLS, it's called the variable arity parameter.

JLS 8.4.1 Format parameters

The last formal parameter in a list is special; it may be a variable arity parameter, indicated by an elipsis following the type.

If the last formal parameter is a variable arity parameter of type T, it is considered to define a formal parameter of type T[]. The method is then a variable arity method. Otherwise, it is a fixed arity method. Invocations of a variable arity method may contain more actual argument expressions than formal parameters. All the actual argument expressions that do not correspond to the formal parameters preceding the variable arity parameter will be evaluated and the results stored into an array that will be passed to the method invocation.

To illustrate in code, this is what varargs allows you to do:

static void f(int... nums) {
    for (int num : nums) {
        System.out.println(num);
    }
}
//...

f(1,2,3); // prints "1", "2", "3"

In contrast, without the varargs construct, you must do this:

static void g(int[] nums) {
    for (int num : nums) {
        System.out.println(num);
    }       
}
//...

g(new int[] { 1, 2, 3 }); // prints "1", "2", "3"

The varargs is what is called a syntactic sugar that hides the verbosity from you.

So to go back to your question, the difference between printMax(double... numbers) and printmax(double numbers[]) is that the first is a variable arity method, meaning you can give it a variable number of parameters. The latter is a fixed arity method, meaning it will accept one and only parameter.

Note the quote above about T... being really a T[]. That is, even with varargs, you can still do the following:

f(new int[] { 1, 2, 3 }); // prints "1", "2", "3"

Here you're manually creating the array to hold the vararg parameters. In fact, if you go as far as decompiling the code, you'll find that just as JLS specified, f does in fact take int[] parameter, and f(1, 2, 3) is implemented as f(new int[] { 1, 2, 3 }).

See also


Varargs gotchas

How varargs are resolved is quite complicated, and sometimes it does things that may surprise you.

Consider this example:

static void count(Object... objs) {
    System.out.println(objs.length);
}

count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!

Due to how varargs are resolved, the last statement invokes with objs = null, which of course would cause NullPointerException with objs.length. If you want to give one null argument to a varargs parameter, you can do either of the following:

count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"

Related questions

The following is a sample of some of the questions people have asked when dealing with varargs:


On when to use varargs

As the previous section showed, varargs can be tricky. Used in the right situations, however, they can lead to much more concise code.

Here's a quote from Effective Java 2nd Edition, Item 42: Use varargs judiciously (emphasis by author):

The lesson is clear. Don't retrofit every method that has a final array parameter; use varargs only when a call really operates on a variable-length sequence of values.

Not only can varargs be confusing, it can also be costly. Effective Java 2nd Edition actually recommends providing fixed-arity overloads for the most common usage scenarios.

Suppose you've determined that 95 percent of the calls to a method have three or fewer parameters. Then declare five overloadings of the method, one for each with zero through three ordinary parameters, and a single varargs for use when the number of parameters exceed three.

The book goes in much greater depth, but essentially you should only use varargs when it actually makes sense. And even in those cases, you may still want to consider providing fixed-arity overloads for performance reasons.

Related question

API links

Here are some examples where varargs makes sense:


On array declarations

Please, please, do not make a habit of declaring arrays like this:

int x[];

You should instead put the brackets with the type, rather than with the identifier:

int[] x;

Note that this is also how arrays are referred to in the above discussions, e.g. T[] int[], etc.

Related questions

polygenelubricants