MessageFormat
class to format a message:
Object[] arguments = { new Integer(7), new Date(), "a disturbance in the Force" }; String result = MessageFormat.format( "At {1,time} on {1,date}, there was {2} on planet " + "{0,number,integer}.", arguments);
It is still true that multiple arguments must be passed in an
array, but the varargs feature automates and hides the process.
Furthermore, it is upward compatible with preexisting APIs. So,
for example, the MessageFormat.format
method now has
this declaration:
public static String format(String pattern, Object... arguments);
The three periods after the final parameter's type indicate
that the final argument may be passed as an array or as a
sequence of arguments. Varargs can be used only in the
final argument position. Given the new varargs declaration for
MessageFormat.format
, the above invocation may be
replaced by the following shorter and sweeter invocation:
String result = MessageFormat.format( "At {1,time} on {1,date}, there was {2} on planet " + "{0,number,integer}.", 7, new Date(), "a disturbance in the Force");
There is a strong synergy between autoboxing and varargs, which is illustrated in the following program using reflection:
// Simple test framework public class Test { public static void main(String[] args) { int passed = 0; int failed = 0; for (String className : args) { try { Class c = Class.forName(className); c.getMethod("test").invoke(c.newInstance()); passed++; } catch (Exception ex) { System.out.printf("%s failed: %s%n", className, ex); failed++; } } System.out.printf("passed=%d; failed=%d%n", passed, failed); } }
This little program is a complete, if minimal, test framework.
It takes a list of class names on the command line. For each
class name, it instantiates the class using its parameterless
constructor and invokes a parameterless method called test. If
the instantiation or invocation throws an exception, the test is
deemed to have failed. The program prints each failure, followed
by a summary of the test results. The reflective instantiation
and invocation no longer require explicit array creation, because
the getMethod
and invoke
methods accept
a variable argument list. The program also uses the new
printf
facility, which relies on varargs. The
program reads much more naturally than it would without
varargs.
So when should you use varargs? As a client, you should take
advantage of them whenever the API offers them. Important uses in
core APIs include reflection, message formatting, and the new
printf
facility. As an API designer, you should use
them sparingly, only when the benefit is truly compelling.
Generally speaking, you should not overload a varargs method, or
it will be difficult for programmers to figure out which
overloading gets called.