How does 'variable length arguments' work in Java? - java

According to my understanding, a method with variable length argument and another method with array as an argument are interchangeable. for eg.
void test(int ... ints){} //method-1
is same as
void test (int [] ints){} //method-2
and we can't use both in the same class (Compile Time Error).
When I use method-1, I can call this method by passing some integers or by passing an array of integers since calling this method using some integers will implicitly create an array of those integers.
For eg.
test(1,2,3); //ok
test(new int[5]); //ok
But,
When I use method-2, I can't call this method by passing some integers as arguments.
test(new int[5]); //ok
test(1,2,3); //NOT OK
Questions:
1) If java implicitly creates an array of the arguments, why it is not able to call test(1,2,3) in case of method-2.
2) Why java doesn't allow using method-1 and method-2 together when both show different behavior?

One difference I could think of is you can have additional arguments to a metod after an int[] but you cant have a variable argument like that. Variable argument should always be the last parameter to a method. Example
void test(int[] a, int a) {} // works fine.
void test(int ... ints, int a){} // compile error.

1) If java implicitly creates an array of the arguments, why it is not
able to call test(1,2,3) in case of method-2.
Because 1,2,3 in test(1,2,3) is not an array, these are three different integers...You have to pass an Array of int to invoke method-2.
2) Why java doesn't allow using method-1 and method-2 together when
both show different behavior?
It creates ambiguity when you call method with array as an argument because array as an argument is allowed in case of varargs as well as array as an argument.
for example, if both method were allowed, test(new int[5]) will create an ambiguity.

The internal representation in the Java compiler of the function declarations in these two cases is identical. That's why the compiler wont let you declare two such functions with the same name.
The difference in the bahivour of these two declarations can be seen when you actually call the functions with the actual arguments. Since Java is a strongly typed language (with strict type checking) it doesn't allow you to pass three integers to the test (int[] a) method.
However, when you call test(int ... a) with test(1,2,3) the compiler generates intermediate code to make a temporary array of three integers and passes it onto the function.

Related

How to dynamically pass arguments as varargs in Java

I'm trying to write a program that will take an unknown number of arrays as input from the user and then print from them, the function that I wrote that print takes in varargs.
So what I'm trying to do is in my main method call print(arr1, arr2, arr3...) and dynamically change that so I don't have to set a restriction on how many arrays can be passed in.
My initial thought process was to store all the arrays in a 2d ArrayList and then unpack them, much like how JavaScript has the spread operator where you can have a 2d array and then do print(...inputArrays), but it doesn't seem like Java allows this.
This method:
public void foo(String... args) {}
is effectively the same as:
public void foo(String[] args) {}
Really - check the bytecode, it's the same signature. Or try to make both of these methods in one class - the compiler won't let you, as they have the same signature. The one difference between String... and String[] is that any callers to String... get the syntax sugar of: Take all arguments passed in this position and create an array for them.
As a consequence, invoking a varargs method and passing in an array works fine:
public void foo(String... args) {
}
String[] a = new String[10];
foo(a); // compiles and runs fine.
The problem is that arrays in java are rather unwieldy, but varargs is based on them. You're on the right track to avoid them, but when trying to dynamically call varargsed methods you're forced into using them. To make matters worse, generics and arrays don't mix well either. Nevertheless:
getPermutations(inputArrayList.toArray(ArrayList[]::new));
should get you somewhere (this converts the arraylist into an array).

why need of "println(char[] x)" when there is already "println(Object x)" - java

I was reading about println function and I came across that there is println(char[ ] x) as well as println(Object x)
https://docs.oracle.com/javase/7/docs/api/java/io/PrintStream.html#println(char[])
My question is that: As arrays in java are object so what is the need to specifically overload println() with char[] whereas rest arrays like int[] etc. uses the println(Object x) overloaded function.
println(Object x)
if you use it to print a char array (the char array is an object), it won't print the content but the objectClass#hashcode style. You can test it yourself to see the exact output.
Because they are implemented differently.
println(Object)
will (after checking for null, etc), call the parameter's toString() method and display the result of it.
The toString() method of an array is not useful: it will give you the array type and the hashcode of the array. So the overloaded form gives a more useful implementation in the case of a char[] parameter.
Note that, with most object types, the toString() method can be overridden (so overloading the println(...) method for every possible type is not necessary (or possible...). However, the toString() method cannot be overridden for arrays, so there is benefit to overloading println in this case.
Because it prints the char array as a string and otherwise prints in object form, and seeing the contents may be more convinient. You can try casting it to object first and see the difference.
Because print/ln(char[]) handles the actual printing of characters, toString() of the array object itself still provides the usual type+hash output, regardless of being an array of characters
char c[]={'a','b','c'};
Object o=c;
System.out.println(c);
System.out.println(c.toString());
System.out.println(o); // *
System.out.println(o.toString());
The * thing is interesting (and this is why I post at all, since the rest is already there in other answers) because it demonstrates that Java has single dispatch: the actual method to be invoked is decided in compilation time, based on the declared type of the argument(s). So it does not matter that o is a character array in runtime, in compilation time it seems to be an Object, and thus print/ln(Object) is going to be invoked for it.

Passing array as argument BUT individually

I want to have an abstract function such as
init(int... conditions);
So that inherited classes can have variety of init conditions; may some classes require less number of arugments and may others will take more than the others.
However I wish to rather pass them individually like following
init(arr[0], arr[1], arr[2]... arr[size-1]);
than
init(arr);
Is such approach possible? If not, then should I be better of just passing an array?
Sorry for the confusion that I seem to create.
I have an array of size n that varies.
I cannot hard code passing the argument because the number of arguments is dependable.
I do not want to go for function overload for different versions of init method because that will create about dozen of different versions of init method.
You don't need to overload the method. Just use the so called variable arguments. The are available in Java since version 1.5. For example:
public void init(int... conditions) { ... }
You can use the method in two ways:
Pass the array itself. Like this:
init(array);
Pass each of the array elements. Like this:
init(array[0], array[1], ... array[n]);
Note that if you want to have other arguments for this method, they should be placed in the method signature only before the variable arguments.
You can always use the variable arguments method parameter. In fact it has the same method signature as what you posted above.
public void init(int... conditions){}
This makes conditions an int[], which you can iterate over to get your init conditions.

Array as method argument

We declare String array like-
String[] a={"A"};
But when a method has String array as argument, why can't we call the method like-
mymethod({"A"});
Code-
class A{
static void m1(String[] a) { }
public static void main(String args[]){
m1(new String []{});//OK
m1({}); //Error
}
}
You can, although your syntax is a bit off.
mymethod(new String[]{"A"});
That's just the way the language is specified. From section 10.6 of the JLS:
An array initializer may be specified in a declaration (§8.3, §9.3, §14.4), or as part of an array creation expression (§15.10), to create an array and provide some initial values.
So you've seen it working in a declaration, and an array creation expression is the form which includes new ArrayElementType at the start:
myMethod(new String[] {"A"});
Bear in mind that when it's part of a declaration, there's only one possible element type involved. For method invocations, it's trickier - there could be multiple overloaded methods, etc. Basically, you'd need to make the expression {"A"} evaluate as a string array on its own, before participating in overload resolution.
For a bit of comparison, the same is true in C#, although C# 3 introduced implicitly typed arrays where the element type is inferred from the values, so you'd be able to write:
// C# 3
MyMethod(new[] {"A"});
You still need the new[] part though.
You can't pass an array like that. Declare it as a variable, then pass the variable to the method instead.

Difference between byte[] and byte ... in Java Methods

Someone asked me what the difference between the two method parameters and why you would use the ... over specifically assigned array.
putMessage(byte ...send)
putMessage(byte[] send)
I couldn't answer them with confidence and couldn't remember what the ... is called.
The ... in your first example are called varargs. Your second example has an array argument. Varargs are a convenience for times when you want to hard code a variable number of arguments to a method but don't want to manually create an array to hold them. It's a shorthand notation. Consider this:
putMessage(0b00100101, 0b00100101, 0b00100101); // varargs
vs. this:
putMessage(new byte[] { 0b00100101, 0b00100101, 0b00100101 }); // array
The first example is less cluttered and more readable.
The parameters with ellipses are generally referred to as "varargs" if you want to google that.
Using varargs allows you to call a method with variable number of arguments without having to specify an array e.g.
public void printStr(String ...strings) {
for (String s : strings) {
System.out.println(s);
}
}
> printStr("Hello", "World")
Hello
World
So varargs allow a certain degree of convenience, but there are downsides - the varargs parameter must be the last parameter in the method signature, and thus you cannot have more than one varargs parameter to a method. If you want to pass multiple arrays to a method you have to use arrays, not varargs.
Another reason you might see arrays in some places where you might expect varargs is that varargs were only introduced in Java 5 - older code and code that needs to be backwards compatible will still be using arrays even where it might make more sense conceptually to use varargs.
The advantage of using varargs in the method signature is flexibility - there are some situations where the caller will have an array ready anyway and some where they will just have several arguments. Varargs will accept either the array or each variable as a separate argument, saving the caller the trouble of instantiating and populating an array.
The first one is with Varargs.
In short
A. First can be used to call with single byte type arg, 2 byte args.. or many args or an array.
B. second will be used with array only.
The ellipsis (three dots) indicates that you are using "varargs".
See http://download.oracle.com/javase/1,5.0/docs/guide/language/varargs.html for more details.
Inside the method, you access the elements of "send" as an array. The two methods are the same in that regard. The convenience is for the caller. In the second putMessage, the caller is compelled to create an array of bytes to pass to putMessage. In the first putMessage, the caller can simply say "putMessage(byte1, byte2)" or "putMessage(byte1, byte2, byte3)" or "putMessage(byte1)" -- variable number of arguments, or varargs.
The ellipses (...) allow you to inline N parameters of a type to a function call without having to define an array first. In the end you do simply get an array of parameters but it's basically shorthand or syntactic sugar. Also your client code might be a little cleaner and more declarative with the ellipses syntax... though it could easily go the other way and become mucky and unreadable.
Here's a great example of the ellipses syntax (variable length argument lists.) While looking at the sample consider what the client code (in the main function) would look like if an array was used instead of a variable length argument list.

Categories

Resources