I'm afraid of varargs. I don't know what to use them for.
Plus, it feels dangerous to let people pass as many arguments as they want.
What's an example of a context that would be a good place to use them?
I'm afraid of varargs. I don't know what to use them for.
Plus, it feels dangerous to let people pass as many arguments as they want.
What's an example of a context that would be a good place to use them?
varargs are useful for any method that needs to deal with an indeterminate number of objects. One good example is String.format. The format string can accept any number of parameters, so you need a mechanism to pass in any number of objects.
String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
etc.
I use varargs frequently for constructors that can take some sort of filter object. For example, a large part of our system based on Hadoop is based on a Mapper that handles serialization and deserialization of items to JSON, and applies a number of processors that each take an item of content and either modify and return it, or return null to reject.
A good rule of thumb would be:
"Use varargs for any method (or constructor) that needs an array of T (whatever type T may be) as input".
That will make calls to these methods easier (no need to do new T[]{...}
).
You could extend this rule to include methods with a List<T>
argument, provided that this argument is for input only (ie, the list is not modified by the method).
Additionally, I would refrain from using f(Object... args)
because its slips towards a programming way with unclear APIs.
In terms of examples, I have used it in DesignGridLayout, where I can add several JComponent
s in one call:
layout.row().grid(new JLabel("Label")).add(field1, field2, field3);
In the code above the add() method is defined as add(JComponent... components)
.
Finally, the implementation of such methods must take care of the fact that it may be called with an empty vararg! If you want to impose at least one argument, then you have to use an ugly trick such as:
void f(T arg1, T... args) {...}
I consider this trick ugly because the implementation of the method will be less straightforward than having just T... args
in its arguments list.
Hopes this helps clarifying the point about varargs.
I have a varargs-related fear, too:
If the caller passes in an explicit array to the method (as opposed to multiple parameters), you will receive a shared reference to that array.
If you need to store this array internally, you might want to clone it first to avoid the caller being able to change it later.
Object[] args = new Object[] { 1, 2, 3} ;
varArgMethod(args); // not varArgMethod(1,2,3);
args[2] = "something else"; // this could have unexpected side-effects
While this is not really different from passing in any kind of object whose state might change later, since the array is usually (in case of a call with multiple arguments instead of an array) a fresh one created by the compiler internally that you can safely use, this is certainly unexpected behaviour.