208

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?

asked Apr 20, 2009 at 0:54
4
  • 3
    I don't see why it would be "dangerous". It's not more dangerous than having a method called a big number of times with different arguments. Do you have concerns with the stack? Then you should not, because varargs are mapped to arrays which are passed by reference. Commented Apr 20, 2009 at 4:47
  • 71
    Just wanted to chime in: there is nothing wrong with avoiding language features you aren't (yet) fully comfortable with. Far better than using features you don't understand! ;) Commented Aug 1, 2011 at 15:55
  • 2
    It is normal to fear of unknown. To learn more read about varargs here docs.oracle.com/javase/tutorial/java/javaOO/arguments.html . You will see, that varargs are nothing to be afraid of. Varargs are useful. Knowing how to use varargs gives you the ability to write methods like [PrintStream.format]("docs.oracle.com/javase/7/docs/api/java/io/…, java.lang.Object...)") :). Commented Nov 19, 2013 at 8:08
  • 2
    This is not a criticism of varargs, but there's actually some reason to "be afraid" (until you precisely understand the limitations of varargs); this is why the @SafeVarargs annotation exists. stackoverflow.com/a/14252221/1593924 Commented Jun 20, 2014 at 7:45

8 Answers 8

157

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);
nbro
16.1k35 gold badges122 silver badges220 bronze badges
answered Apr 20, 2009 at 0:59
Sign up to request clarification or add additional context in comments.

2 Comments

An array parameter also can receive an indeterminate number of objects but a varargs parameter allows more flexibility and convenience at the point of invocation. You can write code to build an array and pass it, or you can let Java do it for you when you choose to receive it in a varargs parameter.
Is there some compelling reason why you wouldn't just pass a reference to some ADT, be it a simple linked list or a more full-grown List object? It could of course still be passed on the stack, just make it a struct with a size/count field in the header.. Varargs just looks like pollution that's been spread around to all languages in the C-family.
80

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 JComponents 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.

answered Apr 20, 2009 at 4:06

4 Comments

Did you consider adding a precondition check if (args.length == 0) throw new RuntimeException("foo"); instead? (Since the caller was violating the contract)
Well, the purpose of a good API is to prevent misuse as early as possible, so at compile time when it's possible, hence the suggestion for void f(T arg1, T... args) that always ensures it is never called with no argument, without need to wait until runtime.
I think most of the time a call to a varargs-only function with no arguments at all will just amount to also do nothing at all. Point is that providing no argument to a varargs function is most likely not going to do considerable harm.
Varargs are useful, but they aren't equivalent to using an array. Varargs are non-reifiable. So, like generics, they're affected by type erasure which could very well be an unacceptable constraint depending on the job.
34

I use varargs frequently for outputting to the logs for purposes of debugging.

Pretty much every class in my app has a method debugPrint():

private void debugPrint(Object... msg) {
 for (Object item : msg) System.out.print(item);
 System.out.println();
}

Then, within methods of the class, I have calls like the following:

debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
 serialNo, ", the grade is ", grade);

When I'm satisfied that my code is working, I comment out the code in the debugPrint() method so that the logs will not contain too much extraneous and unwanted information, but I can leave the individual calls to debugPrint() uncommented. Later, if I find a bug, I just uncomment the debugPrint() code, and all my calls to debugPrint() are reactivated.

Of course, I could just as easily eschew varargs and do the following instead:

private void debugPrint(String msg) {
 System.out.println(msg);
}
debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
 + serialNo + ", the grade is " + grade);

However, in this case, when I comment out the debugPrint() code, the server still has to go through the trouble of concatenating all the variables in every call to debugPrint(), even though nothing is done with the resulting string. If I use varargs, however, the server only has to put them in an array before it realizes that it doesn't need them. Lots of time is saved.

answered Jan 2, 2012 at 1:23

1 Comment

You can implement a debug method in the superclass to print any object using reflection.
13

Varargs can be used when we are unsure about the number of arguments to be passed in a method. It creates an array of parameters of unspecified length in the background and such a parameter can be treated as an array in runtime.

If we have a method which is overloaded to accept different number of parameters, then instead of overloading the method different times, we can simply use varargs concept.

Also when the parameters' type is going to vary then using "Object...test" will simplify the code a lot.

For example:

public int calculate(int...list) {
 int sum = 0;
 for (int item : list) {
 sum += item;
 }
 return sum;
}

Here indirectly an array of int type (list) is passed as parameter and is treated as an array in the code.

For a better understanding, follow this link(it helped me a lot in understanding this concept clearly): http://www.javadb.com/using-varargs-in-java

P.S.: Even I was afraid of using varargs before I thoroughly understood them. But now I'm used to them. As the saying goes, "We cling to the known, afraid of the unknown," so use them as much as you can — and you'll start liking them too. :)

President James K. Polk
42.4k35 gold badges116 silver badges149 bronze badges
answered Sep 25, 2012 at 7:25

1 Comment

C# Equivalent of varargs is "params". It also does the same thing and accepts variable number of parameters. See this for better understanding: dotnetperls.com/params
12

Varargs is the feature added in java version 1.5.

Why to use this?

  1. What if, you don't know the number of arguments to pass for a method?
  2. What if, you want to pass unlimited number of arguments to a method?

How this works?

It creates an array with the given arguments & passes the array to the method.

Example :

public class Solution {
 public static void main(String[] args) {
 add(5,7);
 add(5,7,9);
 }
 public static void add(int... s){
 System.out.println(s.length);
 int sum=0;
 for(int num:s)
 sum=sum+num;
 System.out.println("sum is "+sum );
 }
}

Output :

2

sum is 12

3

sum is 21

answered Oct 13, 2014 at 17:09

Comments

7

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.

answered Apr 21, 2009 at 1:03

6 Comments

Correct, but this example seems a bit far-fetched. Is this likely people will use your API this way?
You never know... And especially when the number of arguments are not hard-coded on the calling side, but also collected say into a list in a loop, passing in an array is not all that uncommon.
I think your use-case example is, generally speaking, not unlikely. One might argue that your API should not use the input array in this way, and if it does, it must document it.
overload the method to support both; argMethod(Object.. objList) argMethod(Object[] objList)
@thetoolman: I don't think that is possible. It will be regarded as a duplicate method.
1

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.

answered Apr 20, 2009 at 1:09

Comments

0

In Java doc of Var-Args it is quite clear the usage of var args:

http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html

about usage it says:

"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. "

answered Aug 3, 2016 at 22:38

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.