Can I pass an array as arguments to a method with variable arguments in Java?

前端 未结 5 1856
我寻月下人不归
我寻月下人不归 2020-11-22 07:52

I\'d like to be able to create a function like:

class A {
  private String extraVar;
  public String myFormat(String format, Object ... args){
    return Str         


        
相关标签:
5条回答
  • 2020-11-22 08:06

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

    0 讨论(0)
  • 2020-11-22 08:10

    jasonmp85 is right about passing a different array to String.format. The size of an array can't be changed once constructed, so you'd have to pass a new array instead of modifying the existing one.

    Object newArgs = new Object[args.length+1];
    System.arraycopy(args, 0, newArgs, 1, args.length);
    newArgs[0] = extraVar; 
    String.format(format, extraVar, args);
    
    0 讨论(0)
  • 2020-11-22 08:11

    It's ok to pass an array - in fact it amounts to the same thing

    String.format("%s %s", "hello", "world!");
    

    is the same as

    String.format("%s %s", new Object[] { "hello", "world!"});
    

    It's just syntactic sugar - the compiler converts the first one into the second, since the underlying method is expecting an array for the vararg parameter.

    See

    • Varargs - J2SE 1.5 Documentation
    0 讨论(0)
  • 2020-11-22 08:15

    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 ]"
    
    0 讨论(0)
  • 2020-11-22 08:19

    I was having same issue.

    String[] arr= new String[] { "A", "B", "C" };
    Object obj = arr;
    

    And then passed the obj as varargs argument. It worked.

    0 讨论(0)
提交回复
热议问题