liveBook · Manning

Variadic arguments

As explained in 100 Java Mistakes and How to Avoid Them

A variadic function or parameter accepts a variable number of arguments, often collecting the supplied values into a sequence of a specified type.

A variadic parameter accepts an arbitrary number of arguments and automatically collects them into an array at the call site. The convenience becomes dangerous when one argument is ambiguous or has the wrong declared type. section 2.9 section 2.15

One argument can change the meaning

For `static void printAll(Object... data)`, `printAll("Hello", "World")` and `printAll(new Object[]{"Hello", "World"})` produce the same array. However, `Object obj = new Object[]{"Hello", "World"}; printAll(obj);` wraps the array inside another array because compilation uses `obj`'s declared type, `Object`, rather than its runtime type. Passing `null` is also hazardous: `printAll(null)` supplies a null array reference and can cause a NullPointerException during iteration. section 2.9.1

static void printAll(Object... data) { 
    for (Object d : data) { 
        System.out.println(d); 
    } 
}

Inspect the minimal `Object...` method to see that callers ultimately provide an array, whether the syntax is flat arguments or an explicit array. section 2.9.1

Collections are not expanded

A generic method such as `contains(T needle, T... haystack)` accepts separate values conveniently, but passing a `List<String>` does not expand the list. The compiler can infer `T` as `Object` and wrap the collection as one element, so the call compiles yet always returns false. Changing an array variable to a collection therefore requires checking every use, not only compiler errors. section 2.9.2

Reduce ambiguity and catch silent behavior changes:

  • Cast deliberately when passing one null: use `(Object)null` for an array containing null, or `(Object[])null` for a null array reference. section 2.9.1
  • Treat array-to-collection changes as semantic changes, and test boolean methods with both true and false cases. section 2.9.2
  • Use IntelliJ IDEA's `Iterable Is Used as Vararg` inspection for collection arguments, while recognizing that static analyzers only warn about some ambiguous calls. section 2.9.2 section 2.9.1

How 100 Java Mistakes and How to Avoid Them covers it

How deep it goes
Explains compiler-time wrapping, declared-type dependence, null behavior, collection nesting, and practical prevention; stops short of full overload-resolution treatment.
Examples
Uses `printAll`, an `Object`-typed array, null casts, and generic `contains` calls with a `List`.
What it assumes
Assumes familiarity with Java method calls, arrays, collections, declared types, and generic type inference.
What you can do after
Diagnose/debug ambiguous calls, unintended array nesting, null failures, and collections accidentally passed as single vararg elements.
How it connects
Connects variadic arguments with arrays, collections, generics, null, compiler type inference, and static analysis.

Also explained in

Compare how 8 books explain variadic arguments →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 Java Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.