After thinking I couldn’t see using the new varargs feature in JDK 5 every day, I thought of a potential use that could cut down on repetitive code: initializing a bean or value object.

As an example, say I wanted to create Person class that contains the person’s first name, middle name, last name, and a nickname. I want all values to default to an empty string if not supplied by the caller.

For a standard Java bean, I could create a class with all the “name” instance variables initialized to the empty string, then write setters for the values. That way, Person bean instances would have the values set by callers, but contain empty strings for any values unset. For convenience, I’d probably include a bulk setter method that would take all four strings. Something like:

setAllNames(String last, String first, String middle, String nick) {
lastName = last;
firstName = first;
middleName = middle;
nickName = nick;
}

But maybe the caller would want to just set the first name and last name. Of course, they could call the method passing in empty parameters:

setAllNames("McQueeney", "Tom", "", "");

but for convenience — especially if there were more the two unneeded parameters, I’d probably want to provide the method:

setLastFirst(String last, String first) {
lastName = last;
firstName = first;
}

And now I can see where having a method that would take a variable number of arguments could help.

As a test, I wrote the following sample Person class. Instead of providing all the setters and getters and creating a bulk setter, as mentioned above, I put all property-setting in the constructor for two reasons: first, to keep the code short, and second, to show that a varargs constructor becomes the default constructor. This seems like a neat little feature. (While in the back of my mind I’m thinking, “How are programmers going to abuse this neat feature?”)

Here’s my Person class, coded using JDK 5.

public class Person {
private String lastName;
private String firstName;
private String middleName;
private String nickName;
public Person(String... params) {
lastName = firstName = middleName = nickName = "";
if (params.length > 0) lastName = params[0];
if (params.length > 1) firstName = params[1];
if (params.length > 2) middleName = params[2];
if (params.length > 3) nickName = params[3];
if (params.length > 4) {
throw new IllegalArgumentException(
"Constructor called with too many arguments"
);
}
}
public String toString() {
return "last: '" + lastName + "', first: '" + firstName +
"', middle: '" + middleName + "', nick: '" + nickName + "'";
}
public static void main(String[] args) {
System.out.println(
"No args: " +
new Person()
);
System.out.println(
"1 arg: " +
new Person("McQueeney")
);
System.out.println(
"2 arg: " +
new Person("McQueeney", "Tom")
);
System.out.println(
"3 arg: " +
new Person("McQueeney", "Tom", "X")
);
System.out.println(
"4 arg: " +
new Person("McQueeney", "Tom", "X", "Spiff")
);
System.out.println(
"5 arg: " +
new Person("McQueeney", "Tom", "X", "Spiff", "bad!")
);
}
}

(I’m not recommending the above coding style as a best-practice!) Here’s the output:

> java -cp . com.mcqueeney.tiger.Person
No args: last: '', first: '', middle: '', nick: ''
1 arg: last: 'McQueeney', first: '', middle: '', nick: ''
2 arg: last: 'McQueeney', first: 'Tom', middle: '', nick: ''
3 arg: last: 'McQueeney', first: 'Tom', middle: 'X', nick: ''
4 arg: last: 'McQueeney', first: 'Tom', middle: 'X', nick: 'Spiff'
Exception in thread "main" java.lang.IllegalArgumentException:
Constructor called with too many arguments
at com.mcqueeney.tiger.Person.<init>(Person.java:19)
at com.mcqueeney.tiger.Person.main(Person.java:51)

The benefit of varargs now is I can provide a bulk property setter with only one method, and allow the caller to pick how many of the properties to set.

Of course, bulk setters like this suffer from the same problems as other bulk setters:

  • You can’t name the parameters, so you have to read the javadocs to figure out what order to pass everything.
  • You still have to provide the missing values for properties in the “middle” of the varargs set that you really don’t want to set.

(By the way, I think the Groovy language allows you to specify the parameter names when you call a method.)

I can see bulk setters using varargs reducing some code. For instance, the <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/GregorianCalendar.html">java.util.GregorianCalendar</a> has constructors that takes initial values for the date and time:

public GregorianCalendar(int year, int month, int dayOfMonth);
public GregorianCalendar(int year, int month, int dayOfMonth,
int hourOfDay, int minute);
public GregorianCalendar(int year, int month, int dayOfMonth,
int hourOfDay, int minute, int second);

which seem like they could be implemented with one Integer varargs constructor, using the new auto-unboxing feature in JDK 5 to easily set the integer properties. (Out of curiosity, I checked the source code for JDK beta 3 Build 60, and, no, they didn’t retrofit GregorianCalendar this way.)

When searching around the Internet for code samples using varargs, one of the more-complete explanations was this Chapter 5 excerpt from Java 1.5 Tiger: A Developer’s Notebook, by Brett McLaughlin and David Flanagan.