In java we can define main() method as both these ways.
public static void main(String[] args) {
System.out.println("Hello World");
}
.
public static void main(String... args) {
System.out.println("Hello World");
}
Both method takes array of String arguments. Now consider following scenario.
String[] arr=new String[10]; // valid
String... arr=new String[10];// invalid
Java never allows to create an array like this wayString... arr=new String[10];. But in above method implementation java allows to do so. My question is how java achieve this two different behavior for two scenarios?
...
is a syntax for method arguments and not for variable definitions. The name of this notation is varargs, which is self explanatory i.e variable number of arguments.
Variable argument or varargs(...) in Java used to write more flexible methods which can accept as many argument as you need not for initialization.
... refers to varargs and its main intention to make method more readable.
void method(String... args) {
}
can be called as
method("a"); OR method("a", "b"); OR method("a", "b", "c");
I see no point in using it in variable declaration, we can't do much with
String... a = {"a", "b"}
An array can anyways be declared with dynamic size
String[] arr = {"a"};
OR
String[] arr = {"a", "b"};
You can use varargs in main because a method declared with varargs (...) is bytecode compatible with a declaration of a method with an array argument (for backwards compatibility). That does not mean that the same syntax is allowed for type declarations.
Related
I just came across varargs while learning android(doInBackground(Type... params)) ,SO posts clarified the use of it
My question is why can't we just use Arrays instead of varargs
public void foo(String...strings) { }
I can replace this type of a call by packing my variable number of arguments in an array and passing it to a method such as this
public void foo(String[] alternativeWay){ }
Also does main(String[] args) in java use varargs , if not how are we able to pass runtime parameters to it
Please suggest the benefits or use of varargs and is there there anything else important to know about varargs
The only difference between
foo(String... strings)
and
foo(String[] strings)
is for the calling code. Consider this call:
foo("a", "b");
That's valid with the first declaration of foo, and the compiler will emit code to create an array containing references to "a" and "b" at execution time. It's not valid with the second declaration of foo though, because that doesn't use varargs.
In either case, it's fine for the caller to explicitly create the array:
for(new String[] { "a", "b" }); // Valid for either declaration
Also does main(String[] args) in java use varargs , if not how are we able to pass runtime parameters to it
When it's written as main(String[] args) it doesn't; if you write main(String... args) then it does. It's irrelevant to how the JVM treats it though, because the JVM initialization creates an array with the command line arguments. It would only make a difference if you were writing your own code to invoke main explicitly.
We could use arrays instead of varargs. Varargs are syntactic sugar for using arrays. But they make your code more compact and more readable. Compare
private void foo(String... ss) { ... }
private void bar() {
...
foo("One", "Two", "Three");
...
}
with
private void foo(String[] ss) { ... }
private bar() {
...
foo(new String[] { "One", "Two", "Three" });
...
}
Similarly, we don't need the diamond operator (<>, Java 7) or lambdas (Java 8) either. But they do make code more readable and therefore more maintainable.
One advantage of varargs is for methods requiring at least one parameter, such as max. With varargs you can do it like this
static int max(int first, int... remaining) {
int max = first;
for (int number : remaining)
max = Math.max(max, number);
return max;
}
This is great, because it is impossible to pass no parameters to the max method, and the calling code for max is really clean: max(2, 4, 1, 8, 9). Without varargs the only way to have enforced the condition that at least one number should be passed would have been to have thrown an exception at runtime if the array had length 0 (always best avoided) or to force the caller to write max(2, new int[] {4, 1, 8, 9}) which is really ugly.
Because you function call looks more like a function call, ex.:
new MyAsyncTask().execute("str1", "str2");
looks better than:
new MyAsyncTask().execute(new String[]{"str1", "str2"});
There is no magic behind AsyncTask, very often you dont really need to pass any parameters, sometimes you pass parameters to constructor instead of execute. There are also implementations of AsyncTask :
https://github.com/roboguice/roboguice/blob/master/roboguice/src/main/java/roboguice/util/SafeAsyncTask.java
that dont use varargs at all
As I understand an array consists of fixed number of elements and a variable length argument takes as many number of arguments as you pass (of the same type). But are they same? Can I pass one where the other is expected?
Yes, if you have a method with a varargs parameter like this:
public void foo(String... names)
and you call it like this:
foo("x", "y", "z");
then the compiler just converts that into:
foo(new String[] { "x", "y", "z"});
The type of the names parameter is String[], and can be used just like any other array variable. Note that it could still be null:
String[] nullNames = null;
foo(nullNames);
See the documentation for varargs for more information.
This does not mean that varargs are interchangeable with arrays - you still need to declare the method to accept varargs. For example, if your method were declared as:
public void foo(String[] names)
then the first way of calling it would not compile.
They are the same, array is internally used by JVM when creating varargs methods. So you can treat vararg argument in the same way you treat array so use for instance enhanced for loop
public void method(String... args) {
for(String name : args) {
//do something
}
}
and call it like this or even pass an array
method("a", "b", "c");
method(new String[] {"a", "b", "c"});
See this nice article for further explanation.
A simple test would suggest that they are the same:
public class test {
public static void varArgs(String... strings) {
for (String s : strings) {
System.out.println(s);
}
}
public static void main(String[] args) {
String[] strings = {"string1", "string2", "string3"};
varArgs(strings);
varArgs("string4", "string5", "string6");
}
}
Outputs:
string1
string2
string3
string4
string5
string6
I am trying to get getIntArrayString to accept parameters given to it, unlike abc.getAverage which uses the field testArray.
edit: Forgot to ask the question.
how would I be able to send parameters such as test1 to getIntArrayString()?
private int testArray;
public static void main(String[] args)
{
int[] testArray = new int[]{2,4,6,8,9};
ArrayHW abc = new ArrayHW(testArray);
System.out.printf(abc.getAverage());
int[] test1= new int[]{3,4,5,6,7};
System.out.printf("Array Values: %s\n",ahw.getIntArrayString());
int[] test1= new int[]{3,4,5,6,7}
System.out.printf("Array Values: %s\n",ahw.getIntArrayString());
}
I'm assuming you have a method named getIntArrayString inside another class. If you want to send the values of test1, the method getIntArrayString must have a parameter of test1's datatype. For example,
public int getIntArrayString(int [] x)
{
}
You should review your knowledge of methods.
Having two variables called testArray may seem a little confusing, but it's not syntactiacally wrong. However, it's less confusing to read your code if you don't, and even better if you remove any unused variables.
You are not posting any error messages, but I suppose you can't compile because you haven't declared any variable "ahw", and ahw.getIntArrayString() produces a compiler error.
In general, in order to be able to send a parameter of type int[] to a method it would be declared like this:
public String getIntArrayString(int[] intArray) { ... }
And you would call it like this
System.out.println(x.getIntArrayList(test1));
where test1 is an int array as declared in your own code.
class Test{
public static void main(String... s){
System.out.println("Hello");
}
}
class Test{
public static void main(String[] s){
System.out.println("Hello");
}
}
What is the difference between above two syntax of main() declaration?
Does Java has any special need to have variable length argument?
No difference (when you run the program from the command line, i.e. what the main method is used for). The first variant appeared after Java 5 introduced varargs.
In short, varargs allows you to pass a variable number of arguments to a method. For the method body the arguments are grouped into an array. Like Test.main("foo", "bar") instead of Test.main(new String[] {"foo", "bar"}). The compiler does the array creation for you behind the scene.
The only difference is if you call main directly from other Java code. The first form allows you to write:
Test.main("first", "second", "third");
whereas the second would require you to create an array explicitly:
Test.main(new String[] { "first", "second", "third" });
Personally I don't think I've ever seen the first form used - calling main from other code is pretty rare. There's nothing wrong with it though.
There is no difference.
In general, String... s allows to pass arguments with comma as separator, while the String[] s requires an array.
But in the implementation s is array in both cases. So ... is sintactic sugar in a sense.
Variable number of arguments main(String... s) was only introduced in Java 5.0.
How come the first call to someMethod doesn't compile without being explicit that it's String[]?
It's fine to use an array initializer to create a String[] array but you can't use it to pass an argument. Are the curly braces used in some other fashion for passing arguments that derails how I'd expect this to behave?
public void someMethod(String[] arr){
//do some magic
}
public void makeSomeMagic(){
String[] arr = {"cat", "fish", "cow"};
//Does not compile!
someMethod({"cat", "fish", "cow"});
//This compiles!
someMethod(new String[]{"cat", "fish", "cow"});
//This compiles!
someMethod(arr);
}
The compiler error is the following:
The method someMethod(String[]) in the type Moo is not applicable for the arguments (String, String, String)
You can only use the { "hello", "world" } initialization notation when declaring an array variable or in an array creation expression such as new String[] { ... }.
See Section 10.6 Array Initializers in the Java Language Specification:
An array initializer may be specified in a declaration, or as part of an array creation expression (§15.10), creating an array and providing some initial values
If you don't want to use explicit String[], use:
public void someMethod(String... arr){
//do some magic
}
…
someMethod("cm", "applicant", "lead");
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.
Read more.
Or you can use varargs:
public void someMethod(String... arr){
//do some magic
}
public void makeSomeMagic(){
someMethod("cat", "fish", "cow");
}
It's basically a fancy syntax for an array parameter (vararg must be the last parameter in method signature).
You can use the curly braces to initialize an array. In every else case it is used to define blocks of statments.