Varargs method changing caller array instead of own copy?

I have this simple varargs method that divides each item in a list:

import java.util.*; class A { static long f(long... xs) { Arrays.sort(xs); long y = 100000000; for (int i = xs.length - 1; i >= 0; i--) y /= xs[i]; return y; } static { System.out.println(f(5,2,6,3,9,3,13,4,5)); long[] xs = new long[]{5,2,6,3,9,3,13,4,5}; System.out.println(Arrays.toString(xs)); System.out.println(f(xs)); System.out.println(Arrays.toString(xs)); } } 

I expect it to pass in a copy of the array, but apparently it is somehow modifying the array I enter, instead of its own local copy:

 $ javac A.java && java A 79 [5, 2, 6, 3, 9, 3, 13, 4, 5] 79 [2, 3, 3, 4, 5, 5, 6, 9, 13] 

So, I wrote this simple test program:

 class B { static void f(Object... os) { System.out.println(os); } static { Object os = new Object[]{1,2,3}; System.out.println(os); f(os); } } 

And it does what I expect, it clones an array of objects before passing it to f (hence the different object identifiers):

 $ javac B.java && java B [Ljava.lang.Object;@1242719c [Ljava.lang.Object;@4830c221 

So, how then can f in A change the caller's array instead of its own copy?

+6
source share
4 answers

Looks like you tricked yourself here:

 Object os = new Object[]{1,2,3}; System.out.println(os); f(os); 

Since os is typed as Object , it is interpreted as the first element of the varargs array. What is passed to the method is actually a new Object[] , the only element of which is your Object[] .

If you do the following, it will print the same instance:

 Object[] os = new Object[]{1,2,3}; System.out.println(os); f(os); 

The f method will need to create a protective copy of the array itself to ensure that the array passed by the calling user is not modified. As Arshajiya points out, varargs are the main parameters of the array, with the β€œbonus” behavior of creating a new array when providing a list of arguments.

In any case, you can use Arrays.copyOf to make a copy that delegates (less type-safe) System.arraycopy .

+14
source

varargs is an array type, but with syntactic sugar that allows you to create arrays on the fly if elements are passed separately as parameters.

That is, these two signatures are identical:

 static long f(long... xs) { static long f(long[] xs) { 

Except that varargs can be called with separate elements instead of an array

Of course, the array will be modified if you bypass creation on the fly and create an array that you must pass.

+3
source

So, how then is f in A changing the array of callers instead of its own copy?

He does not have his own copy. It refers to an array of callers.

+1
source

After all, an array is an object, so you are not modifying the array itself, not its contents, which are allowed.

-1
source

Source: https://habr.com/ru/post/949763/


All Articles