W3docs

Java Varargs (Variable-Length Arguments)

Define Java methods that accept a variable number of arguments using the ... varargs syntax.

A varargs parameter lets a method accept any number of arguments — zero, one, ten, a hundred — of the same type, without forcing the caller to bundle them into an array first. You write the last parameter as Type... name, and inside the method name is an ordinary array of that type.

You've used varargs methods for years. String.format("%s + %s = %s", a, b, c) accepts however many substitution values the format string needs. List.of(1, 2, 3, 4, 5) accepts an arbitrary list of elements. Both rely on varargs.

Declaring a varargs parameter

The syntax is three dots between the element type and the parameter name:

public static int sum(int... numbers) {
  int total = 0;
  for (int n : numbers) total += n;
  return total;
}

Callers pass any number of int arguments:

sum();              // 0
sum(5);             // 5
sum(1, 2, 3);       // 6
sum(1, 2, 3, 4);    // 10

Inside the method, numbers is an int[]. The compiler bundles the loose arguments into an array at the call site.

Varargs is just an array

The body treats the varargs parameter exactly like an array — .length, indexing, for-each, everything:

public static String join(String sep, String... parts) {
  if (parts.length == 0) return "";
  StringBuilder sb = new StringBuilder(parts[0]);
  for (int i = 1; i < parts.length; i++) {
    sb.append(sep).append(parts[i]);
  }
  return sb.toString();
}

join(", ", "red", "green", "blue");   // "red, green, blue"
join("-");                            // ""

Because the parameter is an array, you can also pass a literal array directly:

String[] colors = {"red", "green", "blue"};
join(", ", colors);                   // same as join(", ", "red", "green", "blue")

The compiler accepts either form.

The rules

A few constraints come with the syntax:

  • A method may have at most one varargs parameter. Two would be ambiguous.
  • It must be the last parameter. Otherwise the compiler couldn't tell where the variable arguments end and the next parameter begins.
  • Other parameters come first. Fixed parameters in front, varargs at the tail.
// VALID
public static String tag(String name, String... attrs)   { ... }
public static int    sum(int initial, int... rest)        { ... }

// INVALID
// public static int sum(int... a, int... b)              // two varargs
// public static int sum(int... a, int b)                 // varargs not last

Calling varargs methods

You can pass:

  1. Loose valuesf(1, 2, 3).
  2. An array of the right typef(new int[]{1, 2, 3}).
  3. Nothing at allf(). The method receives an array of length 0, not null.
sum();                       // numbers is int[0]
sum(new int[0]);             // also int[0]
sum(new int[]{1, 2, 3});     // numbers is int[]{1,2,3}

A null argument is a tricky case: sum(null) compiles, treats null as the array itself, and the loop throws NullPointerException. Most varargs methods don't expect null.

Varargs and overloading

Varargs overloads are checked last. A non-varargs overload that matches will be preferred:

public static void show(int a, int b)    { System.out.println("two ints"); }
public static void show(int... xs)        { System.out.println("varargs"); }

show(1, 2);       // "two ints" — fixed-arity wins
show(1);          // "varargs"  — no fixed match
show(1, 2, 3);    // "varargs"

This is good — varargs is the fallback, used only when nothing more specific fits.

A common gotcha: Object...

Varargs of Object accepts anything, including an array:

public static void log(Object... values) {
  for (Object v : values) System.out.println(v);
}

log("a", 1, 2.5);            // 3 calls
String[] names = {"Ada", "Bob"};
log(names);                   // ONE Object[] argument, prints "Ada" then "Bob"
log((Object) names);          // ONE Object argument, prints "[Ljava.lang.String;@..."

The compiler chooses whichever interpretation produces a valid call. With Object..., both interpretations work, and the rules tip towards "treat the array as the varargs array." If you want the array as a single element, cast it: log((Object) names).

A worked example

java— editable, runs on the server

What's next

You can now write methods with the full range of parameter shapes Java offers — fixed, overloaded, recursive, varargs. The final chapter of the methods part returns to the one method every program has: the main method, and what its signature really tells the JVM.

Practice

Practice

Inside a method declared as void f(int... xs), what is the type of xs when no arguments are passed?