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 type T[]. 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 Overflow
Top answer
1 of 6
397

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 type T[]. 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 ]"
2 of 6
211

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

Discussions

java - Spreading array of objects to the list of arguments - Stack Overflow
Communities for your favorite technologies. Explore all Collectives · Stack Overflow for Teams is now called Stack Internal. Bring the best of human thought and AI automation together at your work More on stackoverflow.com
🌐 stackoverflow.com
java - Spread an array into multiple arguments for a function - Stack Overflow
How can I pass an array as three arguments to a function in Java? (Forgive me, I'm very new to Java). I have the following function which takes float r, float g, float b, float a as arguments. rend... More on stackoverflow.com
🌐 stackoverflow.com
July 2, 2017
How to pass an array of elements as separate arguments to a method
I am told this is not allowed. It is. You're probably doing something else than what you're describing. Please show an entire program that you expect should compile and run doing what you describe, but doesn't. More on reddit.com
🌐 r/javahelp
10
2
May 31, 2017
Java Pass Array of Arguments - Stack Overflow
Similar to Can I pass an array as arguments to a method with variable arguments in Java? and varargs and the '...' argument, but the function declaration doesn't use spread syntax. More on stackoverflow.com
🌐 stackoverflow.com
🌐
Baeldung
baeldung.com › home › java › core java › varargs vs array input parameters in java
VarArgs vs Array Input Parameters in Java | Baeldung
January 8, 2024 - When invoking a method with (String[] args), a String array must be passed in as an argument. We can only have one variable-length argument list when defining a method. Varargs is not just limited to the java.lang.String type.
🌐
CodingTechRoom
codingtechroom.com › question › using-the-spread-operator-in-java
Using the Spread Operator in Java: How to Pass Array Elements as Method Arguments - CodingTechRoom
public class Foo { public int ... elements to be specified, as opposed to REST parameters or spread syntax. Use Java Reflection to invoke methods dynamically with an array of arguments....
Top answer
1 of 2
2

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.

2 of 2
0

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 };
}
🌐
Reddit
reddit.com › r/javahelp › how to pass an array of elements as separate arguments to a method
r/javahelp on Reddit: How to pass an array of elements as separate arguments to a method
May 31, 2017 -

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?

Find elsewhere
🌐
Medium
medium.com › @aayushid159 › java-varargs-vs-kotlin-varargs-spread-operator-in-kotlin-eb45b7a6f465
Java Varargs vs Kotlin Varargs & Spread Operator in Kotlin | by Aayushi | Medium
April 6, 2018 - In Java, you pass the array as is, whereas Kotlin requires you to explicitly unpack the array. Technically, this feature is called using a spread operator, but in practice it’s as simple as putting the * character before the corresponding argument:
🌐
Coding Blocks Blog
blog.codingblocks.com › 2016 › the-3-dots-that-brings-a-bit-of-java-to-javascript
The 3 dots that brings a bit of Java to Javascript
December 9, 2018 - Java supports, what it calls as varargs. Which allows us to send and optional number of arguments in form of an array.
🌐
DEV Community
dev.to › paulike › passing-arrays-to-methods-1j71
Passing Arrays to Methods - DEV Community
May 28, 2024 - For an argument of a primitive type, the argument’s value is passed. For an argument of an array type, the value of the argument is a reference to an array; this reference value is passed to the method.
Top answer
1 of 4
2

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.

2 of 4
1

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

🌐
Coderanch
coderanch.com › t › 433533 › java › passing-Array-Varargs-method
passing an Array to a Varargs method... (Java in General forum at Coderanch)
February 28, 2009 - In these cases, it's always wise to cast to either Object[] (if you want the elements to be the actual varargs arguments) or to Object (if you want the array to be one single varargs argument). SCJP 1.4 - SCJP 6 - SCWCD 5 - OCEEJBD 6 - OCEJPAD 6 How To Ask Questions How To Answer Questions
🌐
Programming.Guide
programming.guide › java › passing-list-to-vararg-method.html
Java: Passing a list as argument to a vararg method | Programming.Guide
'String...' behaves similarly to 'String[]', so just use List.toArray to convert your list to an array: yourVarargMethod(yourList.toArray(new String[0]));
🌐
Stack Overflow
stackoverflow.com › questions › 64595816 › java-spread-operator-for-expanding-arrays
Java Spread operator for expanding arrays - Stack Overflow
Hm, but how would you write methods for that? Would you write 100 methods to accept 100 different arities? Passing an array is just more practical.
🌐
Study.com
study.com › computer science courses › computer science 109: introduction to programming
Using Arrays as Arguments to Functions in Java - Lesson | Study.com
November 15, 2021 - In this lesson, you will review the basics of Java arrays. You will also learn how you can pass arrays as arguments to methods in Java, and how to return arrays from methods.
🌐
Baeldung
baeldung.com › home › java › core java › varargs in java
Varargs in Java | Baeldung
January 8, 2024 - String one = firstOfFirst(Arra... an array to hold the given parameters. In this case, the compiler creates an array with generic type components to hold the arguments....
🌐
GitHub
gist.github.com › ORESoftware › 3c4f25de70e9d1849572752c4b59d1a9
Varargs and spread operator in Java · GitHub
Varargs and spread operator in Java · Raw · spread.md · public void run(Condition... c){ } ArrayList<Condition> list = new ArrayList<>(); run(...list); // nope run(list...); // nope run(list); // nope // fml · Sign up for free to join this conversation on GitHub.
🌐
Coderanch
coderanch.com › t › 749149 › java › Variable-method-argument-list
Variable method argument list (Java in General forum at Coderanch)
January 21, 2022 - Hahaha sorry for pulling your leg. It's Saturday and I'm feeling in a silly mood. While "spread syntax" really is a thing, it's not in Java. Anyway, passing an array to a method that takes varargs will work as hoped, as long as the array element type is a subtype of the varargs type.
🌐
Medium
medium.com › @AlexanderObregon › handling-variable-arguments-with-javas-varargs-e578117991a4
Handling Variable Arguments with Java’s varargs | Medium
March 12, 2025 - Passing an already defined array to a varargs method has the same effect as passing individual arguments. The method receives a single array either way, and there is no difference in how the values are processed. Java treats varargs as arrays under the hood, every method that uses varargs is compiled into a method that takes an explicit array parameter.
🌐
GeeksforGeeks
geeksforgeeks.org › java › how-to-pass-an-array-to-a-function-in-java
Passing an Array to a Function in Java - GeeksforGeeks
November 13, 2024 - returnType functionName (datatype arrayName[]) returnType functionName (datatype arrayName[][]) ... // Java Program to Pass an Array to a Function import java.io.*; class GFG { void function1(int[] a) { System.out.println("The first element is: " + a[0]); } void function2(int[][] a) { System.out.println("The first element is: " + a[0][0]); } public static void main(String[] args) { GFG obj = new GFG(); int[] arr1 = { 1, 2, 3, 4, 5 }; int[][] arr2 = { { 10, 20, 30 }, { 40, 50, 60 }, { 70, 80, 90 } }; // passing the 1D array to function 1 obj.function1(arr1); // passing the 2D array to function 2 obj.function2(arr2); } }