I was reading a book about java and the author did some variable arguments. It is something just like this:
public int num(int ... nums){}
and I did some research it looks like nums is simply an array. So I am thinking the above code can be then replaced as:
public int num(int[] nums){}
My question: What is the point of the variable arguments? Can you change the type to other types such as String?
The difference would be in how you can call the method.
If your method looked like this:
public int num(int[] nums){}
you could call it like this:
num(new int[] { 1, 2, 3 });
On the other hand, if you used varargs like this:
public int num(int ... nums){}
you could call it more concisely, like this:
num(1, 2, 3)
Varargs are just syntactic sugar that lets you write
num(1,2,3);
instead of
num(new int[] {1,2,3});
System.out.println("%s %s %s.", "this", "is", "why");
System.out.println("%s %s %s %s?", new String[] {"or", "you", "prefer", "this"});
Varargs (variable arguments) do indeed get packaged into an array when your program is run. There is no functional difference between making a call like this
public int add(int... addends);
and this
public int add(int[] addends);
Java will create an int[] for you and store it in the variable addends in the former. In the latter, you make it so the caller of the add function has to create the array themselves. This can be a bit ugly, so Java made it easy. You call the varargs method like so:
int sum = add(1,2,3,4,5,6);
And you call the array method like so:
int sum = add( new int[] {1,2,3,4,5,6} );
Varargs can be used for more than just primitives, as you suspected; you can use them for Objects (of any flavor) as well:
public Roster addStudents(Student... students) {}
A quote from the article linked:
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.
Edit: Added example for using Objects
Related
Varargs:
public static void foo(String... string_array) { ... }
versus
Single array param:
public static void bar(String[] string_array) { ... }
Java 1.6 seems to accept/reject the following:
String[] arr = {"abc", "def", "ghi"};
foo(arr); // accept
bar(arr); // accept
foo("abc", "def", "ghi"); // accept
bar("abc", "def", "ghi"); // reject
Assuming the above is true/correct, why not always use varargs instead of single array param? Seems to add a touch of caller flexiblity for free.
Can an expert share the internal JVM difference, if there is one?
Thanks.
Arrays have been around from the beginning of Java, while varargs are a fairly recent addition. Thus a lot of older code still happily uses arrays.
Note also that calling a generic vararg method with an explicit array parameter may silently produce different behaviour than expected:
public <T> void foo(T... params) { ... }
int[] arr = {1, 2, 3};
foo(arr); // passes an int[][] array containing a single int[] element
Thus - apart from requiring a lot of effort for no clear benefit - it is not always desirable to replace legacy array parameters with varargs.
Not to mention the cases when you can't, because there is another parameter after the array in the method parameter list:
public void foo(String[] strings, String anotherParam) { ... }
Reordering the parameters may technically solve this, however it breaks client code.
Update: Effective Java 2nd. Edition, Item 42: Use varargs judiciously explains this in more details, giving also a concrete example: Arrays.asList() was retrofitted in Java5 to have vararg parameters, which inadvertently broke a lot of existing code may cause surprises when using this (now obsolete) idiom to print an array:
System.out.println(Arrays.asList(myArray));
Update2: Double checked the source, and it says that the problem occurrs with arrays of primitive types, such as int[]. Before varargs, code like this:
int[] digits = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 4 };
System.out.println(Arrays.asList(digits));
would emit a compilation error, because only arrays of reference types could be converted to a List. Since varargs, and retrofitting asList, the code above compiles without warnings, and the unintended result is something like "[[I#3e25a5]".
The main reason not to specify everything as varargs is that it doesn't always make sense. For example, if InputStream.read(byte[]) where defined as `read(byte...) then the following call would be valid:
myInputStream.read(0, 1, 2, 3);
This would create a 4-element byte array, pass it in and then discard it.
A vararg is simple syntactic sugar for an array.
if you call foo("abc", "def", "ghi"); then
compiler will call it as foo(new String[] {"abc", "def", "ghi"});
compiler will create one new array and pass it to foo().
One can't have both foo(String...) and foo(String[]). Since both are functionally same.
in foo you specify three params,
you would have to call bar like this:
bar(new String[]{"abc", "def", "ghi"});
so that you only call it with one parameter, that is the String[]
in this case this has alsmost nothing to do with internals, your method signature for the method bar simply states that it only has one param, whereas foo has n params which are all strings
This is, how varargs are defined. The varargs extension do not make every array accepting function a varargs function. You have to call bar like this:
bar(new String[]{"abc", "def", "ghi"})
Another difference is efficiency. Objects that are inside an explicit array won't get invoked. However the parameters of a variable argument list are evaluated when the method is pushed on the stack.
This is apparent when a function call is passed as a parameter that returns the type that is used in the variable argument list.
Example:
someMethod( Object... x)
anotherMethod( Object [] );
someMethod( a(), b(), c()); // a, b and c will be invoked before you get into the method.
anotherMethod ( new Object[]{a(), b(), c()}); // The methods aren't invoked until the objects are accessed.
I looked at some Java code today, and I found some weird syntax:
public class Sample {
public int get()[] {
return new int[]{1, 2, 3};
}
}
I thought that can't compile and wanted to fix what I thought was a typo, but then I remembered the Java compiler did actually accept it!
Can someone please help me understand what it means? Is it an array of functions?
It's a method that returns an int[].
Java Language Specification (8.4 Method Declarations)
The declaration of a method that returns an array is allowed to place some or all of the bracket pairs that denote the array type after the formal parameter list. This syntax is supported for compatibility with early versions of the Java programming language. It is very strongly recommended that this syntax is not used in new code.
That's a funny Question.
In java you can say int[] a;, as well as int a[];.
From this perspective, in order to get the same result just need to move the [] and write public int[] get() {. Still looks like the code came from an obfuscator...
As there is a C tag, I'll point out that a similar (but not identical) notation is possible in C and C++:
Here the function f returns a pointer to an array of 10 ints.
int tab[10];
int (*f())[10]
{
return &tab;
}
Java simply doesn't need the star and parenthesis.
java's syntax allows for the following:
int[] intArr = new int[0];
and also
int intArr[] = new int[0];
which looks more fmiliar coming from the c-style syntax.
so too, with a function, the name can come before or after the [], and the type is still int[]
Let's say I have a method m() that takes an array of Strings as an argument. Is there a way I can just declare this array in-line when I make the call? i.e. Instead of:
String[] strs = {"blah", "hey", "yo"};
m(strs);
Can I just replace this with one line, and avoid declaring a named variable that I'm never going to use?
m(new String[]{"blah", "hey", "yo"});
Draemon is correct. You can also declare m as taking varargs:
void m(String... strs) {
// strs is seen as a normal String[] inside the method
}
m("blah", "hey", "yo"); // no [] or {} needed; each string is a separate arg here
You can directly write the array in modern Java, without an initializer. Your example is now valid. It is generally best to name the parameter anyway.
String[] array = {"blah", "hey", "yo"};
or
int[] array = {1, 2, 3};
If you have to inline, you'll need to declare the type:
functionCall(new String[]{"blah", "hey", "yo"});
or use varargs (variable arguments)
void functionCall(String...stringArray) {
// Becomes a String[] containing any number of items or empty
}
functionCall("blah", "hey", "yo");
Hopefully Java's developers will allow implicit initialization in the future
Update: Kotlin Answer
Kotlin has made working with arrays so much easier! For most types, just use arrayOf and it will implicitly determine type. Pass nothing to leave them empty.
arrayOf("1", "2", "3") // String
arrayOf(1, 2, 3) // Int
arrayOf(1, 2, "foo") // Any
arrayOf<Int>(1, 2, 3) // Set explict type
arrayOf<String>() // Empty String array
Primitives have utility functions. Pass nothing to leave them empty.
intArrayOf(1, 2, 3)
charArrayOf()
booleanArrayOf()
longArrayOf()
shortArrayOf()
byteArrayOf()
If you already have a Collection and wish to convert it to an array inline, simply use:
collection.toTypedArray()
If you need to coerce an array type, use:
array.toIntArray()
array.toLongArray()
array.toCharArray()
...
Another way to do that, if you want the result as a List inline, you can do it like this:
Arrays.asList(new String[] { "String1", "string2" });
You can create a method somewhere
public static <T> T[] toArray(T... ts) {
return ts;
}
then use it
m(toArray("blah", "hey", "yo"));
for better look.
Other option is to use ArrayUtils.toArray in org.apache.commons.lang3
ArrayUtils.toArray("elem1","elem2")
I'd like to add that the array initialization syntax is very succinct and flexible. I use it a LOT to extract data from my code and place it somewhere more usable.
As an example, I've often created menus like this:
Menu menu=initMenus(menuHandler, new String[]{"File", "+Save", "+Load", "Edit", "+Copy", ...});
This would allow me to write come code to set up a menu system. The "+" is enough to tell it to place that item under the previous item.
I could bind it to the menuHandler class either by a method naming convention by naming my methods something like "menuFile, menuFileSave, menuFileLoad, ..." and binding them reflectively (there are other alternatives).
This syntax allows AMAZINGLY brief menu definition and an extremely reusable "initMenus" method. (Yet I don't bother reusing it because it's always fun to write and only takes a few minutes+a few lines of code).
any time you see a pattern in your code, see if you can replace it with something like this, and always remember how succinct the array initialization syntax is!.
As Draemon says, the closest that Java comes to inline arrays is new String[]{"blah", "hey", "yo"} however there is a neat trick that allows you to do something like
array("blah", "hey", "yo") with the type automatically inferred.
I have been working on a useful API for augmenting the Java language to allow for inline arrays and collection types. For more details google project Espresso4J or check it out here
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);
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.
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.
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 when I didn't knw abt it. But now I am used to it.
As it is said: "We cling to the known, afraid of the unknown", so just use it as much as you can and you too will start liking it :)
Varargs is the feature added in java version 1.5.
Why to use this?
What if, you don't know the number of arguments to pass for a method?
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
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.
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.
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. "
I've seen an example of it before, but I've never really found any good reference material dealing with it. I know it's possible to pass in several parameters, ints for example, by defining the method as
public void aMethod(int...a)
But I don't know any more about it than that. I've seen an example, and it returned the average of the ints passed.
Is this an out-dated way of passing parameters? Is it even acceptable to use this? What exactly is the syntax like when doing this?
(Some reference material would be great)
It's called varargs (from the C syntax). See Sun's varargs guide for an overview and this JDC Tech Tip for usage. It is not out-dated; it was put in as a feature request since previously you were forced to create an array or list, which was really ugly for supporting something like C's printf.
public void myMethod(String... args) {
for (String aString:args) {
System.out.println(aString);
}
}
You are going to have to pass a list of ints to the method to do this, something like this:
public void aMethod(int[] list)
or this:
public void aMethod(ArrayList<int> list)
It would be nice if Java had something like C#'s params keyword but it doesn't.