skip to content

Varargs

The Type... parameter form, how it desugars to an array, and why it always loses to a more specific overload. Worth knowing for the per-call allocation cost and the compile puzzles interviewers build from it.

part ofJavaoverview, primer and where to startread it →
on this pageshow

questions

5

What are varargs in Java? Show the syntax and explain how the method receives its arguments.

level: juniorimportance: must knowfreq 70%

answer

  1. Type... name = sugar for an array
  2. Must be the LAST parameter, at most one
  3. Zero args = empty array, never null
  4. Compiler allocates the array per call
  5. JDK: String.format, List.of, Arrays.asList

basics

~20 s

Varargs (variable arguments) let a method accept any number of arguments of one type, written as Type... name. Inside the method, name is an array. You call it like sum(1, 2, 3) or pass an array.

solid answer

~40 s

Varargs let a method take a variable number of arguments of a single type, declared with an ellipsis: void log(String... parts). At the call site you pass zero, one, or many comma-separated values, and the compiler wraps them into an array — so inside the method the parameter is exactly a String[]. You can also pass an existing array directly. The varargs parameter must be the last formal parameter, and a method may have at most one. Because it becomes an array, you iterate it with a normal loop or for-each, and parts.length tells you how many were passed. Common JDK examples are String.format, Arrays.asList, and List.of. Calling with no arguments yields an empty (length-0) array, not null, so it's safe to iterate without a null check.

code

java · 13 lines
java
int sum(int... numbers) {        // numbers is an int[]
    int total = 0;
    for (int n : numbers) {       // safe even when empty
        total += n;
    }
    return total;
}

// All valid calls:
sum();                 // empty array, returns 0
sum(5);                // [5]
sum(1, 2, 3);          // [1, 2, 3]
sum(new int[]{4, 5});  // pass an array directly

go deeper

for a junior

Knows the Type... syntax, that it accepts any number of args, and that inside the method it's an array you can loop over.

for a middle

Adds that it must be the last parameter, max one, that zero args means an empty (not null) array, and that you can pass an array directly.

for a senior

Explains it as pure call-site sugar over an array parameter, notes the per-call array allocation, and cites JDK examples and the Object... type-safety trade-off.

for a principal

Frames varargs API-design guidance: prefer fixed params plus varargs for the 'at least N' case, beware Object... eroding type safety, and weigh allocation cost in hot paths.

## What problem varargs solve Before Java 5 (2004), if you wanted a method to accept "any number of values," you had two awkward options: write many overloads (`sum(int)`, `sum(int,int)`, `sum(int,int,int)`, …) or force the caller to build an array first (`sum(new int[]{1,2,3})`). **Varargs** (short for *variable-arity arguments* / *variable arguments*) is syntactic sugar that lets a single method declaration accept a variable count of arguments while the caller writes a plain comma-separated list. ## Syntax You declare a varargs parameter by putting three dots (an *ellipsis*) between the type and the parameter name: ```java int sum(int... numbers) { ... } ``` Rules of the declaration: - **It must be the last formal parameter.** `void f(String prefix, int... values)` is legal; `void f(int... values, String suffix)` is a compile error. - **A method may have at most one varargs parameter.** - It can be preceded by ordinary (fixed) parameters, which the caller must always supply. ## What it actually is: an array The key mental model: **a varargs parameter is just an array parameter with sugar at the call site.** `int... numbers` is, inside the method body, exactly an `int[] numbers`. The compiler, at each call site, *gathers* the loose arguments and *allocates a new array* to hold them, then passes that array. So these two calls are equivalent: ```java sum(1, 2, 3); // compiler creates new int[]{1,2,3} sum(new int[]{1, 2, 3}); // you pass the array yourself ``` Because it's an array inside the method, you use it like any array: `numbers.length`, indexing `numbers[i]`, or a for-each loop. ## The empty case If you call `sum()` with no arguments, the parameter is an **empty array** (`length == 0`), **never `null`**. That means you can safely iterate it without a null check — a frequent point of confusion. ## Common library examples Varargs is everywhere in the JDK: `String.format(String, Object...)`, `Arrays.asList(T...)`, `List.of(E...)`, `Stream.of(T...)`, `Collections.addAll(Collection, T...)`, and printf-style logging APIs. Recognizing the `...` in a signature tells you the method is varargs. ## A note on `Object...` A very general varargs is `Object...`, which can accept anything (autoboxing converts primitives). This is what `String.format`'s argument list uses. It is flexible but loses compile-time type checking on those arguments, so use specific types when you can. ## Summary Varargs = `Type... name`, last parameter, max one per method, materialized as an array inside the method, empty-array (not null) for zero arguments. It's purely caller-side convenience over an array parameter.

  • Can you pass an existing array where a varargs parameter is expected?
    Yes. Because the varargs parameter is an array, you can pass an array of the matching type directly, e.g. sum(new int[]{1,2,3}). The compiler passes it through without re-wrapping.
  • Why must the varargs parameter be last?
    The compiler needs an unambiguous boundary: everything after the fixed parameters is gathered into the varargs array. If a fixed parameter followed the varargs, the compiler couldn't tell where the variable-length list ends.

saying these in an interview costs you the question

  • Saying a no-argument call gives null instead of an empty array
  • Thinking varargs can appear anywhere in the parameter list
  • Claiming you can have multiple varargs parameters
  • Believing varargs is a special runtime type rather than just an array

context

open as a page

What is the runtime cost of calling a varargs method, and when does it matter?

level: middleimportance: should knowfreq 45%

basics

~10 s

Each varargs call (with loose arguments) creates a new array on the heap to hold them. That allocation is cheap individually but adds up on hot paths called millions of times, creating garbage-collection pressure.

open as a page

When should you use varargs, and what are common pitfalls and alternatives?

level: middleimportance: should knowfreq 40%

basics

~20 s

Use varargs when a method naturally takes 'any number' of one type, like log(String...) or sum(int...). Avoid forcing it where a list is clearer, and require at least one mandatory value with a fixed first parameter when zero arguments make no sense.

open as a page

How do varargs participate in overload resolution? Describe the phases the compiler uses to pick a method.

level: seniorimportance: should knowfreq 55%

basics

~10 s

When choosing between overloaded methods, the compiler tries non-varargs (fixed-arity) matches first. Only if none fit does it consider varargs methods. So a more specific fixed overload always beats a varargs one.

open as a page

What hazards arise when combining varargs with generics, and what is @SafeVarargs for?

level: seniorimportance: nice to knowfreq 30%

basics

~20 s

Mixing generics with varargs creates a generic array under the hood, which Java can't fully type-check, so the compiler warns about possible 'heap pollution.' If the method only reads the array safely, you annotate it @SafeVarargs to suppress the warning.

open as a page