6.1. Getting Started with Varargs

In Java, variable arity arguments, more commonly referred to as varargs, enable us to write methods that accept a variable number of arguments of the same type. Consider the usual way to do this using an array. Here is an example of a min method in a class named Helper that returns the smallest integer in an int array:

public static int min(int[] numbers)

Use the following command to download the starter code for this chapter and place it into a subdirectory called cs1302-varargs:

sh -c "$(curl -fsSl https://cs1302uga.github.io/cs1302-book/_bundle/cs1302-varargs.sh)"

You can call Helper.min elsewhere like this:

int smallest1 = Helper.min(new int[] { 5, 1, -1, 3 });
int smallest2 = Helper.min(new int[] { 4, 3, 1 });
int smallest3 = Helper.min(new int[] { 42, 1024 });

The code snippet above is a little tedious because it requires the creation and use of an array. The following will not work as-is, but it would be nice if we would could just supply the numbers as individual arguments instead of using an array directly:

int smallest1 = Helper.min(5, 1, -1, 3);
int smallest2 = Helper.min(4, 3, 1);
int smallest3 = Helper.min(42, 1024);

You can accomplish this for the example above using method overloads; however, that would require us to define at least three different versions of Helper.min, one for each number of arguments. That is even more tedious than using a single array parameter. Even if we are willing to write additional overloads, how many parameters will the method need to support? Is it seven? Zero? One hundred? We may not know what that number is ahead of time. In this situation, overloads just do not scale and adding them just introduces more places for bugs to appear.

Instead of writing several overloads, we will rework the method to accept a variable number of arguments using a varargs parameter. In Java, a varargs parameter is a method parameter that includes ... (three dots) immediately after the data type in its declaration. Here is a declaration for an array variable and a varargs variable, respectively, so that you can compare the syntax:

An array parameter.
int[] numbers
A varargs parameter.
int... numbers

From a caller’s perspective, the change from int[] to int... indicates that zero or more int arguments can be supplied when calling the method. Inside the method, there is no change. The parameter is still treated as if it were an array variable to an int[].

Using this new approach, we can add the functionality we desire to Helper.min with only a single definition for the method. No overloads are needed! Here is the signature before and after the varargs parameter is used:

Declared with an array parameter.
public static int min(int[] numbers) {
    ...
} // min
Declared with a varargs parameter.
public static int min(int... numbers) {
   ...
} // min

Check yourself

Adjust the min method in Helper.java in the starter code to support a variable number of int arguments, then confirm that it works as intended by adjusting the calls to Helper.min that appear in Driver.java.

Sample Solution(s)

The only change that you need to make in Helper.java is to the numbers parameter of the min method. The exact adjustment is shown earlier in the section.

Likewise, the only changes that you need to make in Driver.java are to the lines that call the Helper.min method. The exact adjustment is shown earlier in the section.

You should also try to call the updated version of Helper.min with an array. If you made the adjustments mentioned above, the new version of Helper.min should work when supplied with either a single array argument of type int[] or zero or more int arguments.

There are two important rules related to varags parameters in Java:

  1. a method can only have up to one varargs parameter; and

  2. if a method has a varargs parameter, then it must be the last parameter declared in its parameter list.

These rules enable us to require a minimum number of arguments when the method is called without writing any code to explicitly check the array length. Of course, that can still be done, if needed. The rules also prevent us from writing potentially ambiguous code involving varargs. Here are some quick examples:

This method accepts one or more int arguments.
public static int sum(int num, int... nums) {
    ...
} // sum
This will not compile. The varags parameter must be last.
public static int sum(int... nums, int nums) {
    ...
} // sum
This will not compile. At most one varags parameter is allowed.
public static int sum(int... nums1, int... nums2) {
    ...
} // sum

The last example would result in ambiguous calls if it were allowed. That is, once two or more arguments are supplied in a call, the compiler has no way to determine which array the arguments belong to.