🧩 Methods · Beginner

Varargs in Java

Type... args, must be last, received as an array.

🧩 The mysteryString.format("%s and %s", a, b) takes 3 arguments. Add another %s and it takes 4. How can one method accept any number of arguments?

The three dots

A varargs parameter, written Type... name, lets callers pass zero or more arguments of that type. Inside the method it's simply an array: nums.length, nums[0] and for-each all work.

static int sum(int... nums) {
    int total = 0;
    for (int n : nums) total += n;
    return total;
}
🔮 Predict it

Your turn

What prints?

static int total(int... n) {
    int t = 0;
    for (int x : n) t += x;
    return t;
}
void main() {
    System.out.println(total());
    System.out.println(total(4, 5, 6));
}
  1. 0 15
  2. Compile error
  3. null 15
Show the answer

Calling with no arguments is legal: Java passes an empty array (length 0), never null. So the loop runs zero times and returns 0. Three arguments become an array of length 3.

Three ways to call

Callers can pass nothing (an empty array arrives), several values (Java packs them into a new array), or an existing array (used directly as the varargs array).

sum();                 // nums = {}
sum(1, 2);             // nums = {1, 2}
sum(new int[]{4, 5});  // that array
🔮 Predict it

Your turn

What prints?

static void show(String... xs) {
    System.out.println(xs.length);
}
void main() {
    show(new String[]{"a", "b", "c"});
    show("solo");
}
  1. 3 1
  2. 1 1
  3. 3 3
Show the answer

The String[] passed directly is the varargs array (length 3). The single value "solo" is wrapped into a new array of length 1.

⚠️ The trap

Zero means zero

Varargs means zero or more. If the method blindly reads xs[0], then first() compiles fine and throws ArrayIndexOutOfBoundsException at runtime. Handle the empty case, or require one normal parameter first.

static int first(int... xs) {
    return xs[0]; // boom when empty
}
// safer: at least one is required
static int max(int first, int... rest)

Where the dots may go

✗ Won't compile
void log(Object... args, String level)
void log(int... a, String... b)

Varargs must be the LAST parameter, and there can be only one: otherwise Java can't tell where the variable part ends.

✓ Compiles
void log(String level, Object... args)

Fixed parameters first, then a single varargs at the end.

💼 In the real world

In real projects

You use varargs daily: printf, String.format, List.of(...), Arrays.asList(...). Remember from overloading that varargs are tried last. And creating that array costs a little, which is why List.of has separate overloads for 0 to 10 elements and only falls back to varargs beyond that.

Key takeaways

  1. int... nums arrives inside the method as an int[]
  2. Callers can pass nothing, several values, or an existing array
  3. Only one varargs parameter, and it must come last
  4. Overload resolution tries varargs methods last
🤯 Did you know?

Varargs arrived in Java 5 (2004), and static void main(String... args) is a perfectly valid way to write a classic main method.

Practice questions

What does this print?

static int count(String... words) {
    return words.length;
}
void main() {
    System.out.println(count());
    System.out.println(count("a", "b", "c"));
}
  1. 1 3
  2. Compile error
  3. 0 3
  4. null 3
Check your answer

0 3. With no arguments, Java passes an empty array (length 0), never null. Three arguments become an array of length 3.

Which declaration compiles?

  1. static void log(Object... args, String level)
  2. static void log(String level, Object... args)
  3. static void log(int... a, String... b)
Check your answer

static void log(String level, Object... args). The varargs parameter must be last, and there can be only one. Otherwise the compiler couldn't tell where the variable part of the arguments ends.

Next: why can you call Math.max(3, 4) without ever creating a Math object, but not .length() without a String?