varargs and the '...' argument

44,531

Solution 1

From the docs on varargs:

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.

So you can pass multiple arguments or an array.

The following works just fine:

class VarargTest {
  public static void main(String[] args) {
    Object[] params = {"x", 1.2345f};
    String s = String.format("%s is %.2f", params);
    System.out.println(s); // Output is: x is 1.23
  }
}

Solution 2

You can just pass an array:

public void foo(String... args) {
}

String args[] = new String[10];
foo(args);

Solution 3

The situation you are describing is going to be fairly rare: most of the time, your varargs items will be Strings, or numbers, or Widgets... it will be unusual for them to be Objects (which could be anything) or arrays.

But if the varargs argument is a bunch of Objects or an array type, then your question does arise: you can pass it a single array and then how will the compiler know whether you meant to pass an array (the one you provided), or an series of 1 item which it should PUT into an array for you?

A quick test shows the answer:

public class TestClass {
    public static void main(String[] args) {
        Object anObject = new Object();
        Object[] anArray = new Object[] {anObject, anObject};
        System.out.println("object1 = " + anObject);
        System.out.println("array1 = " + anArray);
        takesArgs();
        takesArgs(anObject, anObject);
        takesArgs(anArray); // is this the same as array1?
        takesArgs(anArray, anArray);
    }

    public static void takesArgs(Object... stuff) {
        System.out.println("The array was " + stuff);
    }
}

The result of executing (your exact numbers will vary:

object1 = java.lang.Object@3e25a5
array1 = [Ljava.lang.Object;@19821f
The array was [Ljava.lang.Object;@addbf1
The array was [Ljava.lang.Object;@42e816
The array was [Ljava.lang.Object;@19821f
The array was [Ljava.lang.Object;@9304b1

So the answer is that in ambiguous cases it treats what you passed as the array instead of creating a new array to wrap it. This makes sense as you could always wrap it in an array yourself if you wanted the other interpretation.

Share:
44,531

Related videos on Youtube

Martijn Courteaux
Author by

Martijn Courteaux

I'm writing Java, C/C++ and some Objective-C. I started programming in 2007 (when I was 11). Right now, I'm working on my magnum opus: an iOS, Android, OS X, Linux, Windows game to be released soon on all relevant stores. The game is written in C++ using SDL and OpenGL. A couple of seeds for my name (for java.util.Random, radix 26): 4611686047252874006 -9223372008029289706 -4611685989601901802 28825486102

Updated on December 15, 2020

Comments

  • Martijn Courteaux
    Martijn Courteaux over 3 years

    Consider the method declaration:

    String.format(String, Object ...)
    

    The Object ... argument is just a reference to an array of Objects. Is there a way to use this method with a reference to an actual Object array? If I pass in an Object array to the ... argument - will the resultant argument value be a two-dimensional array - because an Object[] is itself an Object:

    Object[] params = ....; // Make the array (for example based on user-input)
    String s = String.format("%S has %.2f euros", params);
    

    So the first component of the array (Which is used in the String.format method), will be an array and he will generate:

    [class.getName() + "@" + Integer.toHexString(hashCode())] 
    

    and then an error because the array size is 1.

    The bold sequence is the real question.
    This is a second question: Does a ... array/parameter have a name?

    • Martijn Courteaux
      Martijn Courteaux over 14 years
      Sorry, I had to test it before asking... I think I had this problem a long time ago.
  • Esko
    Esko over 14 years
    I'm not going to even bother adding my own answer, edit in "... is known as vararg or variable arguments and requires 0..n elements of specified elements" or something like that.
  • Bart van Heukelom
    Bart van Heukelom over 13 years
    So if you want to call the method with a single argument and it happens to be an array, you have to explicitly wrap it in another. method(new Object[]{array});
  • amara
    amara almost 13 years
    or do method((Object)array), which will auto-wrap
  • Sizons
    Sizons almost 9 years
    I'm better off than before I saw these explanations about vararg parameters, yet I still just don't get it.