简体   繁体   中英

How to pass varargs by reference in Java

I'm writing a method that receives any number of arguments and returns them modified. I have tried with varargs but it doesn't work, here you can see a simplified version of the code:

public static void main(String[] args) {
   String hello = "hello";
   String world = "world";

   addPrefix(hello, world);

   System.out.println("hello: " + hello + "  world: " + world);
}

public static void addPrefix(String... elements) {
   for (int i = 0; i < elements.length; i++) {
      elements[i] = "prefix_" + elements[i];
   }

   for (int i = 0; i < elements.length; i++) {
      System.out.println(elements[i]);
   }
}

Printed result:

prefix_hello    
prefix_world    
hello: hello  world: world

As you can see, the values are modified correctly inside the method, but the original vars have not changed.

I have looked at many pages like here and here but it seems that Java copies the values of the vars to an Object[] , so the references are lost.

Any idea of how could I do it?

Java is pass by value . You cannot achieve what you wish. Instead you can return the modified array from addPrefix() function.

public static void main(String args[]) {

    String hello = "hello";
    String world = "world";

    String[] elements = addPrefix(hello, world);

    for (int i = 0; i < elements.length; i++) {
        System.out.println(elements[i]);
    }




}

public static String[] addPrefix(String... elements) {
    for (int i = 0; i < elements.length; i++) {
        elements[i] = "prefix_" + elements[i];
    }

    for (int i = 0; i < elements.length; i++) {
        System.out.println(elements[i]);
    }

    return elements;
}

and output

prefix_hello
prefix_world
prefix_hello
prefix_world

An array of String[] can be passed to fulfill the vararg requirement - no copy/clone of the array passed as such is made so mutating the array inside .. well, changes that array everywhere. But this is ugly, particularly because it adds a "side-effect, sometimes".

However, you cannot do "by reference" 1 otherwise as a new array is created when arguments are passed normally to a variadic method as in the original code.

// but avoid code like this, if possible
String[] words = {"hello", "world"};
addPrefix(words);
System.out.println("hello: " + words[0] + "  world: " + words[1]);

1 It's only Call by Reference if rebinding a parameter changes a binding in the caller, which Java does not support . It doesn't matter if varargs are used or not.

"prefix_" + elements[i] creates a new object, which is put into the array elements . You have to return elements to get the modified variables.

You can not.Java only does call-by-value. See How to do call by reference in Java? and Is Java "pass-by-reference" or "pass-by-value"?

You could return an Array of strings with the new strings and use this

You can't do it .

Change the method signature as List, then, you can expect this pass-by-reference behavior. Here, you are passing each argument individually, and java makes them as array internally and to the processing further.

This is a classic example of how many people dont know the way in which varargs works. Varargs is simply a holder for an array which is created when the methods with varargs parameter is invoked. To make my point clearer,we must have a look at the bytecode of varargs:-

Your code this

String hello = "hello";
String world = "world";
addPrefix(hello, world);

becomes to this

addPrefix(new String[]{hello, world});

Since you do not have reference to your newly created array,you are simply printing the values of your original String objects ,hello and world

You need to explicity return the array reference and iterate over it to view the changes

public static String[] addPrefix(String... elements) {
   for (int i = 0; i < elements.length; i++) {
      elements[i] = "prefix_" + elements[i];
   }

   for (int i = 0; i < elements.length; i++) {
      System.out.println(elements[i]);
   }
  return elements;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM