5.3 Allowing Zero-Length Argument Lists
One particularly nice feature
about varargs is that a variable-length argument
can take from zero to n arguments. This means that you can actually
invoke one of these methods without any parameters, and things still behave. On the other hand, this means that, as a programmer, you better
realize you must safeguard against this condition.
5.3.1 How do I do that?
Remember in "Iterating Over Variable-Length Argument Lists," you saw
this simple method:
You can call this method in several ways:
public static int max(int first, int... rest) {
int max = first;
for (int i : rest) {
if (i > max)
max = i;
}
return max;
}
What's not so nice is that there are many cases where you may already
int max = MathUtils.max(1, 4);
int max = MathUtils.max(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
int max = MathUtils.max(18, 8, 4, 2, 1, 0);
have the numbers to pass in stored as an array, or at least in some collected
form:
It's impossible to just pass these numbers on to the max( ) method. You
// Get the numbers from some method
int[] numbers = getListOfNumbers( );
would need to check the list length, and strip off the first object (if it's
available), then check the type to ensure it's an int. That would be
passed in, along with the rest of the array (which can be iterated over, or
converted manually to a suitable format). In general, this process is a real
pain and is a lot of work for what should be trivial. To get around this,
remember that this method is treated by the compiler as the following:
NOTEAutounboxing helps some, as "Integer" objects are freely converted to``` "int"
public static int max(int first, int[] rest)
primitives. Autounboxing is covered in Chapter 4.So, by extension, you could convert max( ) to look like this:
You've now created a method that can easily be used with arrays:
public static int max(int... values) {
int max = Integer.MIN_VALUE;
for (int i : values) {
if (i > max)
max = i;
}
return max;
}
While using a single variable-length argument made this task easier, it
// Get the numbers from some method
int[] numbers = getListOfNumbers( );
int max = MathUtils.max(numbers);
introduces problems if you pass in a zero-length arrayin the best case,
you're going to get unexpected results. To account for this, you now need
a little error checking. Example 5-3 is a complete code listing for the
MathUtils class, which at this point is more of a MathUtil class!
Example 5-3. Handling zero-argument methods
Anytime you have the possibility for a zero-length argument list, you
package com.oreilly.tiger.ch05;
public class MathUtils {
public static int max(int... values) {
if (values.length == 0) {
throw new IllegalArgumentException("No values supplied.");
}
int max = Integer.MIN_VALUE;
for (int i : values) {
if (i > max)
max = i;
}
return max;
}
}
need to perform this type of error checking. Generally, a nice informative
IllegalArgumentException is a great solution.
5.3.2 What about...
...invoking this same method with normal non-array arguments? That's
perfectly legal, of course. The following are all legitimate ways to invoke
the max( ) method:
NOTEWhatever you do, please don't throw a checked exceptionyou just add hassle
int max = MathUtils.max(myArray);
int max = MathUtils.max(new int[] { 2, 4, 6, 8 });
int max = MathUtils.max(2, 4, 6, 8);
int max = MathUtils.max(0);
int max = MathUtils.max( );
for programmers using your code, and for what is a fringe case, rather than a
normal problem.