Java Varargs: Methods with Variable-Length Arguments - Quiz

Total: 5 questions

1. 

What is varargs in Java and how do you declare a method with a variable number of arguments?

Varargs (short for variable arguments) is Java syntax that lets you declare a method accepting a variable number of arguments. The feature was introduced in Java 5. A variable-length parameter is declared with three dots after the type: static void test(int... array).

Such a method can be called with any number of arguments, including none: test(), test(1), test(1, 2, 3), and you can also pass an existing array — test(new int[]{1, 2, 3}).

The JDK relies on varargs everywhere: System.out.printf(String, Object...), String.format(String, Object...), List.of(E...), Arrays.asList(T...).

2. 

What rules apply to a varargs parameter when you declare a method?

There are three rules:

1. The varargs parameter must come last in the parameter list: static void test(double d, int... array) is valid, while static void test(int... array, double d) does not compile — otherwise the compiler could not tell where the variable-length list ends.

2. A method can declare only one varargs parameter: static void test(int... a, double... b) is a compile error.

3. Inside the method the parameter is an ordinary array: length, indexing, the for-each loop and Arrays.toString() are all available.

The same rules apply to methods, constructors, abstract and generic methods. The entry point can use varargs too: public static void main(String... args) is completely equivalent to String[] args.

3. 

What does a varargs parameter receive when the method is called with no arguments, and why is test(null) dangerous?

Varargs is syntactic sugar over arrays: the compiler builds the array at the call site, so test(1, 2, 3) and test(new int[]{1, 2, 3}) are indistinguishable after compilation.

A call with no arguments delivers an empty array, not null, so array.length returns 0 and a for-each loop simply does no iterations. An if (array == null) check is pointless for normal call sites.

However, calling test(null) on test(String... s) passes null as the whole array rather than as "one null element", and the very next s.length throws NullPointerException. To pass a single null element write test((String) null).

4. 

How does the compiler resolve overloads that involve varargs, and when does the ambiguity error occur?

The compiler resolves the call in three phases and moves on to the next phase only when the current one produces no applicable candidate:

1. Strict invocation — exact match and primitive widening, no autoboxing and no varargs: test(3) picks test(int a).

2. Loose invocation — autoboxing/unboxing is allowed, varargs is still ignored: test(3) picks test(Integer a).

3. Variable-arity invocation — only now are varargs methods considered: test(1, 2) picks test(int... a).

Hence the golden rule: a varargs method is always considered last. When several varargs methods are applicable in phase 3, the compiler picks the most specific one — test(int... array) is more specific than test(double... array), because int widens to double.

If no candidate is more specific (for example test(boolean... a) and test(int... a) for the call test()), the compiler reports reference to test is ambiguous — the code never compiles, so the JVM never sees it. The way out is an explicit empty array test(new int[0]) or giving the methods different names.

5. 

What is the @SafeVarargs annotation for, and what is heap pollution?

When a varargs parameter has a generic type (T... or List<String>...), the compiler warns about possible heap pollution: because of type erasure an array of List<String> is really a List[] at runtime, so anything can be stored into it and the failure surfaces later as a ClassCastException.

If the method only reads the elements and never writes into the array, the warning is suppressed with @SafeVarargs:

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

The annotation may only be applied to methods that cannot be overridden: static and final methods, constructors, and since Java 9 also private methods. On a regular instance method it is a compile error, because a subclass could break the safety you promised.

Page 1 of 1