What are varargs in Java, and how does the compiler turn a varargs call into an array?
Varargs, short for variable arguments, let a method accept any number of arguments of one type. You declare them with three dots after the last parameter type: int... values. Inside the method, that parameter behaves exactly like an array.
What the compiler does at the call site is the interesting part. When you call sum(1, 2, 3), the compiler creates a new array, fills it with the arguments, and passes it. When you call sum(existingArray), that array is passed straight through with no copying at all. So a varargs call always compiles down to a single array argument, and the compiler picks the cheapest form available.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
System.out.println("sum(1, 2, 3) : " + sum(1, 2, 3));
System.out.println("sum(10, 20) : " + sum(10, 20));
int[] existing = {5, 5, 5};
System.out.println("sum(array) : " + sum(existing));
System.out.println("as array : " + Arrays.toString(asArray(1, 2, 3)));
}
static int sum(int... values) {
int total = 0;
for (int v : values) {
total += v;
}
return total;
}
static int[] asArray(int... values) {
return values;
}
}Two rules catch people out. A varargs parameter must be the last parameter of the method, so you cannot have int... values, int extra. And a method may have only one varargs parameter. Both are compile errors.
On when to use them: varargs are a good fit for the last parameter of a method whose job is to gather a variable number of same-typed values, such as a formatting helper or a logger. They are a poor fit for the first of several similar overloads, because the compiler prefers the fixed-arity version and the overload resolution becomes hard to follow. A common objection is that varargs allocate an array on every call even for a single argument, which matters only in a measured hot path.