Item 42: Use varargs judiciously
1. Varargs methods accept zero or more arguments of a specified type. The varargs facility works by first creating an array whose size is the number of arguments passed at the call site, then putting the argument values into the array, and finally passing the array to the method.
2. You can retrofit an existing method that takes an array as its final parameter to take a varargs parameter instead with no effect on existing clients. But just because you can doesn’t mean that you should! It was a big mistake to enable varargs for Arrays.asList. Before Java 1.5, Arrays.asList only takes Object[] as parameter and will reject int[] at compile time. However after varargs is enabled for it, it will take int[] as one element and make an array of int[] as the parameter. Instead of retrofitting Arrays.asList, it would have been better to add a new method to Collections specifically for the purpose of gathering its arguments into a list:
public static <T> List<T> gather(T... args) { return Arrays.asList(args); }
3. Don’t retrofit every method that has a final array parameter; use varargs only when a call really operates on a variable-length sequence of values.
4. Every invocation of a varargs method causes an array allocation and initialization. If you have determined empirically that you can’t afford this cost but you need the flexibility of varargs, there is a pattern that lets you have your cake and eat it too. Suppose you’ve determined that 95 percent of the calls to a method have three or fewer parameters. Then declare five overloadings of the method:
public void foo() { } public void foo(int a1) { } public void foo(int a1, int a2) { } public void foo(int a1, int a2, int a3) { } public void foo(int a1, int a2, int a3, int... rest) { }
The EnumSet class uses this technique for its static factories to reduce the cost of creating enum sets to a bare minimum.