Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between double... and double[] in formal parameter type declaration

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[]?


1 Answers

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

  • Java language guide/varargs

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:

  • bug with varargs and overloading?
  • How to work with varargs and reflection
  • Most specific method with matches of both fixed/variable arity (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

  • Java’s varargs performance.

API links

Here are some examples where varargs makes sense:

  • java.util.Arrays.asList(T...)
  • java.util.PrintStream.printf(String format, Object... args)
  • java.lang.reflect.Method.invoke(Object obj, Object... args)

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

  • Is there any difference between Object[] x and Object x[] ?
  • Difference between int[] myArray and int myArray[] in Java
  • in array declaration int[] k,i and int k[],i
    • These declarations result in different types for i!
like image 52
polygenelubricants Avatar answered Jan 31 '26 07:01

polygenelubricants



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!