Yes, a T... is only a syntactic sugar for a T[].
JLS 8.4.1 Format parameters
The last formal parameter in a list is special; it may be a variable arity parameter, indicated by an elipsis following the type.
If the last formal parameter is a variable arity parameter of type
T, it is considered to define a formal parameter of typeT[]. The method is then a variable arity method. Otherwise, it is a fixed arity method. Invocations of a variable arity method may contain more actual argument expressions than formal parameters. All the actual argument expressions that do not correspond to the formal parameters preceding the variable arity parameter will be evaluated and the results stored into an array that will be passed to the method invocation.
Here's an example to illustrate:
public static String ezFormat(Object... args) {
String format = new String(new char[args.length])
.replace("\0", "[ %s ]");
return String.format(format, args);
}
public static void main(String... args) {
System.out.println(ezFormat("A", "B", "C"));
// prints "[ A ][ B ][ C ]"
}
And yes, the above main method is valid, because again, String... is just String[]. Also, because arrays are covariant, a String[] is an Object[], so you can also call ezFormat(args) either way.
See also
- Java language guide/varargs
Varargs gotchas #1: passing null
How varargs are resolved is quite complicated, and sometimes it does things that may surprise you.
Consider this example:
static void count(Object... objs) {
System.out.println(objs.length);
}
count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!
Due to how varargs are resolved, the last statement invokes with objs = null, which of course would cause NullPointerException with objs.length. If you want to give one null argument to a varargs parameter, you can do either of the following:
count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"
Related questions
The following is a sample of some of the questions people have asked when dealing with varargs:
- bug with varargs and overloading?
- How to work with varargs and reflection
- Most specific method with matches of both fixed/variable arity (varargs)
Vararg gotchas #2: adding extra arguments
As you've found out, the following doesn't "work":
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(myArgs, "Z"));
// prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
Because of the way varargs work, ezFormat actually gets 2 arguments, the first being a String[], the second being a String. If you're passing an array to varargs, and you want its elements to be recognized as individual arguments, and you also need to add an extra argument, then you have no choice but to create another array that accommodates the extra element.
Here are some useful helper methods:
static <T> T[] append(T[] arr, T lastElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
arr[N] = lastElement;
return arr;
}
static <T> T[] prepend(T[] arr, T firstElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
System.arraycopy(arr, 0, arr, 1, N);
arr[0] = firstElement;
return arr;
}
Now you can do the following:
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(append(myArgs, "Z")));
// prints "[ A ][ B ][ C ][ Z ]"
System.out.println(ezFormat(prepend(myArgs, "Z")));
// prints "[ Z ][ A ][ B ][ C ]"
Varargs gotchas #3: passing an array of primitives
It doesn't "work":
int[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs only works with reference types. Autoboxing does not apply to array of primitives. The following works:
Integer[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
Answer from polygenelubricants on Stack OverflowYes, a T... is only a syntactic sugar for a T[].
JLS 8.4.1 Format parameters
The last formal parameter in a list is special; it may be a variable arity parameter, indicated by an elipsis following the type.
If the last formal parameter is a variable arity parameter of type
T, it is considered to define a formal parameter of typeT[]. The method is then a variable arity method. Otherwise, it is a fixed arity method. Invocations of a variable arity method may contain more actual argument expressions than formal parameters. All the actual argument expressions that do not correspond to the formal parameters preceding the variable arity parameter will be evaluated and the results stored into an array that will be passed to the method invocation.
Here's an example to illustrate:
public static String ezFormat(Object... args) {
String format = new String(new char[args.length])
.replace("\0", "[ %s ]");
return String.format(format, args);
}
public static void main(String... args) {
System.out.println(ezFormat("A", "B", "C"));
// prints "[ A ][ B ][ C ]"
}
And yes, the above main method is valid, because again, String... is just String[]. Also, because arrays are covariant, a String[] is an Object[], so you can also call ezFormat(args) either way.
See also
- Java language guide/varargs
Varargs gotchas #1: passing null
How varargs are resolved is quite complicated, and sometimes it does things that may surprise you.
Consider this example:
static void count(Object... objs) {
System.out.println(objs.length);
}
count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!
Due to how varargs are resolved, the last statement invokes with objs = null, which of course would cause NullPointerException with objs.length. If you want to give one null argument to a varargs parameter, you can do either of the following:
count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"
Related questions
The following is a sample of some of the questions people have asked when dealing with varargs:
- bug with varargs and overloading?
- How to work with varargs and reflection
- Most specific method with matches of both fixed/variable arity (varargs)
Vararg gotchas #2: adding extra arguments
As you've found out, the following doesn't "work":
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(myArgs, "Z"));
// prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
Because of the way varargs work, ezFormat actually gets 2 arguments, the first being a String[], the second being a String. If you're passing an array to varargs, and you want its elements to be recognized as individual arguments, and you also need to add an extra argument, then you have no choice but to create another array that accommodates the extra element.
Here are some useful helper methods:
static <T> T[] append(T[] arr, T lastElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
arr[N] = lastElement;
return arr;
}
static <T> T[] prepend(T[] arr, T firstElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
System.arraycopy(arr, 0, arr, 1, N);
arr[0] = firstElement;
return arr;
}
Now you can do the following:
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(append(myArgs, "Z")));
// prints "[ A ][ B ][ C ][ Z ]"
System.out.println(ezFormat(prepend(myArgs, "Z")));
// prints "[ Z ][ A ][ B ][ C ]"
Varargs gotchas #3: passing an array of primitives
It doesn't "work":
int[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs only works with reference types. Autoboxing does not apply to array of primitives. The following works:
Integer[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"
The underlying type of a variadic method function(Object... args) is function(Object[] args). Sun added varargs in this manner to preserve backwards compatibility.
So you should just be able to prepend extraVar to args and call String.format(format, args).
Actually, because for compatibility reasons, the signature of a method, which is using varargs function(Object... args) is the equivalent of a method declared with an array function(Object[] args).
Therefore in order to pass and spread any collection to function which expects varargs, you need to transform it to the array:
import java.util.Arrays;
import java.util.stream.Stream;
public class MyClass {
static void printMany(String ...elements) {
Arrays.stream(elements).forEach(System.out::println);
}
public static void main(String[] args) {
printMany("one", "two", "three");
printMany(new String[]{"one", "two", "three"});
printMany(Stream.of("one", "two", "three").toArray(String[]::new));
printMany(Arrays.asList("foo", "bar", "baz").toArray(new String[3]));
}
}
All these calls of printMany will print:
one
two
three
It's not exactly the same as spread operator, but in most cases, it's good enough.
In java there is concept of Variable Arguments, using which you can pass different numbers of arguments to same function.
I am taking your code as an example :
public class Foo {
public int doSomething (int ...a) {
int sum = 0;
for (int i : a)
sum += i;
return sum;
}
}
Now you can call this function as :
doSomething (args)
For more information you can visit below link : http://www.geeksforgeeks.org/variable-arguments-varargs-in-java/
java - Spreading array of objects to the list of arguments - Stack Overflow
java - Spread an array into multiple arguments for a function - Stack Overflow
How to pass an array of elements as separate arguments to a method
Java Pass Array of Arguments - Stack Overflow
Use
yourDataStructure.addAll(Arrays.asList(arrayOfObjects));
this makes use of the addAll() method with a Iterable<Some_Type> you mentioned in your question.
addAll is a method that "iterates" over the collection and adds all elements to another datastructure.
Iterable, for you this would be Iterable, creates a datastructure called an iterator that allows you to iterate over the datastructure yourself.
Object[] arrayOfObjects = new Object[size];
Collection<Object> myNewCollection = new ArrayList<Object>();
// use the addAll
myNewCollection.addAll(arrayOfObjects);
// use an iterator
Iterator<Object> iter = myNewCollection.iterator();
while(iter.hasNext()){
Object object = iter.next();
// do something with the object
}
This is a typical example of an "X-Y Problem". Your original quest was to somehow group the 3 different parameters that you want to pass to a function. That's "problem X". Then you came up with the idea of using an array for this, but you were still unsure how to go about it, so you posted this question asking how to best use an array to achieve what you want. But that's "problem Y", not "problem X".
Using an array may and may not be the right way of solving "problem X". (Spoiler: it isn't.)
Honoring the principle of the least surprise, the best way of solving your problem "X" in my opinion is by declaring a new class, FloatRgba which encapsulates the four floats in individual float members: final float r; final float g; final float b; final float a;.
So, then your rgbToFloat() method does not have to return an unidentified array of float, instead it becomes a static factory method of FloatRgba:
public static FloatRgba fromIntRgb( int r, int g, int b )
{
return new FloatRgba( r / 255f, g / 255f, b / 255f, 1.0f );
}
Finally, you introduce a utility function prepareRenderer which accepts a Renderer and a FloatRgba and invokes renderer.prepare(float, float, float, float) passing it the individual members of FloatRgba.
This way you keep everything clear, self-documenting, and strongly typed. Yes, it is a bit inconveniently verbose, but that's java for you.
Maybe late for the original question, might help late readers stumbling over here (like me), though: I rather recommend converting just one single parameter to float:
public static float rgbToFloat(int value)
{
return value / 255.0f;
// don't need the cast, value will be promoted to float anyway
// as second parameter is already
}
Call now gets to
renderer.prepare(rgbToFloat(25), rgbToFloat(60), rgbToFloat(245), 1);
Sure, the draw back is that you have to call it three times now (as the other way round, you would have had to store the array in a temporary as shown in the comments, you wouldn't, in comparison, have gained much either), in the end, you gain flexibility for and additionally avoid the temporary array object when none is needed.
If you still insist on the array, you'll need a temporary
float[] rgb = rgbToFloat(r, g, b);
renderer.prepare(rgb[0], rgb[1], rgb[2], 1.0f);
But then I wonder why you don't consider alpha as well:
public static float[] rgbToFloat(int r, int g, int b)
{
return rgbToFloat(r, g, b, 255);
}
public static float[] rgbToFloat(int r, int g, int b, int a)
{
return new float[] { r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f };
}
So I have a method as follows....
public void display(String ...names) {
ArrayList<String> allNames = new ArrayList<String>();
for (String name : names) {
allNames.add(name);
}
}
I then have a String[] array String[] names of names collected from a command line. I want to be able to pass these strings all at once into the method, but when I try this:
display(names);
I am told this is not allowed. Is there anyway I can pass all of these Strings into the method at once without knowing the size of the String[] array?
You can do this with reflection, but it's probably more performant to use cached method handles that you initialize once, then reuse as many times as you need.
class SpreadInvoker {
public static void draw1(int x, String y) {
System.out.printf("draw1(%s, %s)%n", x, y);
}
public void draw2(int x, int y) {
System.out.printf("draw2(%s, %s)%n", x, y);
}
static MethodHandle DRAW1;
static MethodHandle DRAW2;
public static void main(String[] args) throws Throwable {
DRAW1 = MethodHandles.lookup()
.findStatic(
SpreadInvoker.class,
"draw1",
MethodType.methodType(
void.class,
int.class,
String.class
)
)
.asSpreader(Object[].class, 2);
DRAW2 = MethodHandles.lookup()
.findVirtual(
SpreadInvoker.class,
"draw2",
MethodType.methodType(
void.class,
int.class,
int.class
)
).asSpreader(Object[].class, 2);
SpreadInvoker instance = new SpreadInvoker();
final Object[] args1 = { 13, "twenty-six" };
final Object[] args2 = { 13, 26 };
DRAW1.invoke(args1); // SpreadInvoker.draw1(13, "twenty-six")
DRAW2.invoke(instance, args2); // instance.draw2(13, 26)
}
}
Output:
draw1(13, twenty-six)
draw2(13, 26)
Note, however, that this is the sort of thing you'd do if you don't know what method you need to call at compile time. This sort of thing should almost never be necessary.
This style of calling methods is not usual for Java language, but possible with reflection API:
Method drawMethod = YourClass.class.getDeclaredMethod("draw", new Class[] { int.class, int.class });
drawMethod.invoke(null, (Object[]) args);
Further reading