Varargs
What Are Varargs?
Sometimes you don't know in advance how many arguments a method call will need. Should a sum() method accept two numbers? Three? Ten? Java solves this with variable-length arguments, or varargs, using the ellipsis (...) syntax:
returnType methodName(Type... name) { ... }A varargs parameter lets the caller pass zero, one, or many arguments of that type, separated by commas, without wrapping them in an array themselves. Internally, the compiler packages whatever you pass into a regular array, so inside the method body "name" behaves exactly like a Type[].
A sum() method using varargs
public class VarargsDemo {
static int sum(int... numbers) {
int total = 0;
for (int n : numbers) { // numbers is just an int[] here
total += n;
}
return total;
}
public static void main(String[] args) {
System.out.println(sum()); // 0 arguments
System.out.println(sum(5)); // 1 argument
System.out.println(sum(1, 2, 3)); // 3 arguments
System.out.println(sum(new int[] { 4, 5, 6 })); // an array works too
}
}0 5 6 15
Where You've Already Seen Varargs
Varargs show up throughout the standard library once you know to look for them:
String.format("Hello %s, you are %d", name, age) — accepts any number of format arguments
List.of("a", "b", "c") — builds an immutable list from any number of elements
System.out.printf("%s scored %d%n", player, score) — same varargs pattern as format
Arrays.asList(1, 2, 3) — turns any number of arguments into a fixed-size List
Rules for Declaring Varargs
The ellipsis (...) goes immediately after the type: Type... name
A method can take other regular parameters alongside a varargs parameter
The varargs parameter, if present, must be the LAST parameter in the list
A method can declare at most one varargs parameter
Mixing regular and varargs parameters
static void logMessage(String level, String... details) {
System.out.println("[" + level + "] " + String.join(", ", details));
}
logMessage("INFO", "server started");
logMessage("ERROR", "disk full", "retrying", "attempt 3");void bad1(int... a, int... b) // two varargs parameters — illegal
void bad2(int... a, String name) // varargs not last — illegal
Overload Resolution: Varargs vs. Fixed Arity
If you overload a method with both a fixed-arity version and a varargs version, Java always prefers the more specific, exact-match overload first. The varargs version is only chosen as a fallback when no fixed-arity overload matches.
Fixed-arity overload wins when it matches exactly
static void report(int a, int b) {
System.out.println("Fixed-arity version: " + a + ", " + b);
}
static void report(int... values) {
System.out.println("Varargs version, count: " + values.length);
}
public static void main(String[] args) {
report(1, 2); // matches the fixed-arity overload exactly
report(1, 2, 3); // no fixed-arity match -> falls back to varargs
report(); // no fixed-arity match -> falls back to varargs
}Fixed-arity version: 1, 2 Varargs version, count: 3 Varargs version, count: 0
Best Practices
Use varargs for genuinely optional, homogeneous, trailing arguments (formatting, logging, factory methods)
Avoid varargs when the number of arguments is fixed and known — a regular parameter list is clearer
Be careful overloading a varargs method with primitives — autoboxing and varargs together can create ambiguous calls
Remember that calling a varargs method allocates a new array under the hood, which matters in hot loops