Varargs in Java

A variable arity parameter lets a method accept any number of arguments, and inside the method it is simply an array.

Definition

A varargs parameter, written with three dots after the type, accepts zero or more arguments of that type. The compiler packs them into an array before the call.

Why it exists

Before varargs, a method that accepted an unknown number of values needed either an explicit array at every call site or a family of overloads. Varargs removes that noise for the caller.

Syntax and example

public static int sum(int... values) {
    int total = 0;
    for (int value : values) {   // values is an int[]
        total += value;
    }
    return total;
}
System.out.println(sum());              // 0, an empty array
System.out.println(sum(5));             // 5
System.out.println(sum(5, 10, 15));     // 30
System.out.println(sum(new int[]{1, 2}));   // 3, an array may be passed directly

Rules

  • A method may have at most one varargs parameter.
  • It must be the last parameter in the list.
  • Inside the method it is an ordinary array, so length and indexing work.
  • It is never null when called normally; with no arguments it is an empty array.
public static String join(String separator, String... parts) {   // correct
    return String.join(separator, parts);
}

// public static String join(String... parts, String separator)  // will not compile

Where it is used in the standard library

System.out.printf("%s is %d%n", "age", 30);   // Object... args
List<String> cities = List.of("Pune", "Kochi", "Surat");   // E... elements
int biggest = Collections.max(List.of(3, 9, 4));

Overloading and varargs

static void report(String message)        { System.out.println("exact"); }
static void report(String... messages)    { System.out.println("varargs"); }

report("hello");   // prints "exact" - varargs is the last resort

The compiler considers a varargs method only after exact matches, widening and boxing have all failed. That makes behaviour stable when an overload is added later, but it can also surprise you.

The generic varargs warning

@SafeVarargs
public static <T> List<T> listOf(T... items) {
    return new ArrayList<>(Arrays.asList(items));
}

An array of a generic type cannot be created safely, so the compiler warns about a possible heap pollution. When the method only reads the array and never stores anything into it or exposes it, the warning can be suppressed with @SafeVarargs. The annotation is allowed only on methods that cannot be overridden, which means static, final or a constructor.

Common mistakes

  • Passing null as the only argument. sum(null) passes a null array rather than an empty one, and the loop then throws.
  • Assuming a primitive array widens. sum(new Integer[]{1, 2}) does not match int....
  • Using varargs for a fixed number of arguments, which throws away compile time checking.
  • Placing the varargs parameter anywhere but last.

Best practices

  • Use varargs only where the count genuinely varies.
  • If at least one argument is required, declare it separately: process(String first, String... rest). That makes the requirement a compile error rather than a runtime check.
  • Do not overload a varargs method with a similar fixed arity one unless the choice is obvious.
  • Remember the hidden array allocation on every call in a hot loop.

Practice

  1. Write a method that returns the largest of any number of int values and throws when called with none.
  2. Why does sum() return 0 rather than throwing?
  3. Predict what report("a", "b") prints in the overload example above.
  4. Change join so the separator comes last, and explain the compiler error.

Conclusion

Varargs is convenience for the caller and an array for the implementer. Keep it last, keep it genuinely variable, and require the first argument separately when the method needs at least one.

Written by Lorens Mishra

Default administrator account created by the installer.

Continue reading

All Java notes →
Java

Recursion in Java

A recursive method calls itself on a smaller problem, and it works only when a base case guarantees the shrinking stops.

Read more
Java

Pass by Value in Java

Java always passes arguments by value. For objects the value copied is the reference, which explains every result that looks like pass by reference.

Read more
Java

Methods in Java

A method groups a piece of behaviour behind a name, a parameter list and a return type, and that signature is the contract callers depend on.

Read more

Discussion

0 comments
Sign in to join the discussion.

No comments yet. Be the first to say something.