JavaVarargs

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:

Java
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

Java
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

Java
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");
Warning
A method can declare at most one varargs parameter, and it must be the last parameter. Both of these fail to compile:

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

Java
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
Note
Java's overload-resolution algorithm runs in phases: it first looks for an exact match without varargs or boxing, then with boxing, and only in the final phase does it consider varargs. This is why a matching fixed-arity method is always preferred over a varargs method — the varargs form is treated as the least specific candidate.
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