简体   繁体   English

如何在Java中通过引用传递varargs

[英]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: 我已经尝试使用varargs,但是它不起作用,在这里您可以看到代码的简化版本:

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. 我在这里这里都看过很多页面,但是似乎Java将vars的值复制到Object[] ,因此引用丢失了。

Any idea of how could I do it? 我该怎么办?

Java is pass by value . Java是按价值传递的 You cannot achieve what you wish. 您无法实现自己想要的。 Instead you can return the modified array from addPrefix() function. 相反,您可以从addPrefix()函数返回修改后的数组。

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. 一个阵列 String[]可以被传递到满足可变参数的要求 -这样被制造成突变内的数组传递阵列中的复制/克隆..以及,无处不在改变了阵列。 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. 但是,您不能“通过引用” 1进行操作,否则,当将参数正常传递给可变参数方法时(如原始代码一样),将创建一个新数组

// 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 . 1这只是通过引用调用 ,如果重新绑定参数改变主叫绑定,它的Java 支持 It doesn't matter if varargs are used or not. 是否使用varargs无关紧要。

"prefix_" + elements[i] creates a new object, which is put into the array elements . "prefix_" + elements[i]创建一个新对象,该对象放入array elements You have to return elements to get the modified variables. 您必须返回elements以获取修改后的变量。

You can not.Java only does call-by-value. 您不能,Java只按值调用。 See How to do call by reference in Java? 请参见如何使用Java进行引用调用? and Is Java "pass-by-reference" or "pass-by-value"? Java是“按引用传递”还是“按值传递”?

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. 将方法签名更改为List,然后,您可以期待这种通过引用的行为。 Here, you are passing each argument individually, and java makes them as array internally and to the processing further. 在这里,您将分别传递每个参数,而java将它们作为数组在内部进行进一步处理。

This is a classic example of how many people dont know the way in which varargs works. 这是一个典型的例子,说明有多少人不知道varargs的工作方式。 Varargs is simply a holder for an array which is created when the methods with varargs parameter is invoked. Varargs只是数组的持有者,该数组是在调用带有varargs参数的方法时创建的。 To make my point clearer,we must have a look at the bytecode of varargs:- 为了使我的观点更清楚,我们必须看一下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 由于您没有引用新创建的数组,因此仅打印原始String对象,hello和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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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