How to use Java varargs

Freya - October 12, 2015

The three dots in a method parameter type is a feature called Java varargs. It was introduced in Java 5 and is formally known as variable arity methods or variadic functions.

What is varargs

Varargs methods accept zero or more arguments (args) of a given type. Such methods can have a variable number of arguments and thus useful for passing of dynamic data.

//int varargs example
public void myIntMethod(int... args){
    // body
}

//String varargs example
public void myStringMethod(String... args){
    // body
}

The varargs methods work by first creating an array whose size is a number of arguments that is passed to the function. Then the values are put into that array and the array is passed further to the method.

Here is a simple example where we pass integers and return the sum:

static int sum(int... args) {
	int sum = 0;
	for(int arg : args) {
		sum += arg;
	}
	
	return sum;
}

There are several ways to call this sum() function:

sum(); // possible, but useless
sum(2, 5, 7);
sum(2);
sum(new Integer[]{1, 2, 3});

Varargs parameter order

Varargs is a parameter passed into a method. It should always go last.

This is good:

static int sum(String a, int b, int... args) {
   //body
}

These ones are not allowed:

//not OK
static int sum(int... args, String a, int b) {
   //body
}

//not OK
static int sum(String abc, int... args, int b) {
   //body
}

Varargs are effective in cases where you really do want a method with a variable number of arguments. You can easily change an existing method that takes an array to take a varargs parameter instead. But just because you can do it – don’t!

Use varargs cautiously

Java is an easy language to use also due to its convenient conversions of objects into primitives and vice versa. Here’s a post about 7 Golden rules of conversions.

Because of these builtin conversions you should be particularly careful with varargs.

Type-checking

Consider these two examples:

int method1(Object... args) {}
<T> String method2(T... args) {}

These methods will accept ANY parameter list. Any compile-time type-checking will be lost and you could easily get an exception in run-time.

Extra allocations

Every invocation of a varargs method causes an array allocation and initialization. Consider this when developing performance-critical applications. It is often a better solution to implement several overloadings of the method:

public int sum(int a, int b);
public int sum(int a, int b, int c);
public int sum(int a, int b, int c, int... args);

In this case only when the number of parameters exceeds 3 an additional array will be created.

Unexpected behavior

There is some unexpected behavior in cases when the caller passes in an explicit array to the method. In this case you will receive a shared reference to that array. You would need to remember to clone the array before changing it:

String[] args = new String[] {"a", "b", "c"} ;

varargsMethod(args);  // this is not the same as varargsMethod("a", "b", "c");

args[2] = "d";  // this changes the array

When to use varargs

Although you should be careful when using varargs, there are several cases when it actually a good thing. A good rule considering varargs would be: Use it for any method that needs an array of T as input and you are unsure how many arguments it would be.

Formatting

There are often cases when we need to pass a variable number of parameters into String.format() method:

String myStringFormat(String template, String... args) {    
    return String.format(template, args);
}

Output

Varargs can be useful to output strings into console or log.

private void debug(String... msg) {
    for (String item : msg) {
       System.out.print(item);
   }
}

In summary varargs are a convenient way to define methods that take a variable number of arguments, but they should not be overused. They can produce unexpected results if used inappropriately.

See Also

Comments

Any comments? Create a new discussion on GitHub.
There used to be an inline comment form here, but it was removed.