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:
int[] numbers
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:
public static int min(int[] numbers) {
...
} // min
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:
a method can only have up to one varargs parameter; and
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:
public static int sum(int num, int... nums) {
...
} // sum
public static int sum(int... nums, int nums) {
...
} // sum
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.