27

I have trouble with scope of variable.

public static void main(String[] args){
    int[] test={1,2,3};
    test(test);
    System.out.println(test[0]+" "+test[1]+" "+test[2]);
}

static void test(int[] test){
    test[0]=5;
}

I expected the output to 1 2 3, but the result was 5 2 3. Why I changed the value in the array in the method, but the original array changed?

user2864740
  • 60,010
  • 15
  • 145
  • 220
purblue
  • 275
  • 1
  • 3
  • 5
  • 2
    Because you're modifying the state of the object... – Luiggi Mendoza Feb 08 '14 at 23:23
  • Don't get confused by the name of the parameter. Change the parameter name to `whatever` in your `test(..)` method, it won't affect anything. – Sotirios Delimanolis Feb 08 '14 at 23:23
  • @SotiriosDelimanolis I don't really get your comments in this question =\ – Luiggi Mendoza Feb 08 '14 at 23:24
  • @LuiggiMendoza OP states `Why I changed the value in the array in the method, but the original array changed?` I'm under the impression they think the array is copied or something. – Sotirios Delimanolis Feb 08 '14 at 23:25
  • 5
    To the OP: this has nothing to do with scope. You passed an object reference value to a method, and modified the object via that reference inside your method. That's how Java (and C, and ...) works. See: [Oracle tutorial on the subject](http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html) – Brian Roach Feb 08 '14 at 23:26
  • 1
    @SotiriosDelimanolis that would be passing by value, and if you think about it (I mean, think about passing just the value of the array), that would be *right*. But you instead pass a copy of the reference, so if you change the state of the object (in this case, an entry in the array), then the *original* object will be modified as well. – Luiggi Mendoza Feb 08 '14 at 23:26
  • @LuiggiMendoza Right, if that's their misunderstanding, then it's a duplicate. They also seem to be confused about scope of variables, maybe thinking that `test` in `main` is related somehow to `test` in `test(..)`. – Sotirios Delimanolis Feb 08 '14 at 23:27
  • so, How can I do that keep the original array, and just use the copy of the array in the method? Even though I made an new array like 'int[] temp=test' in the method, the same situation occurred. – purblue Feb 08 '14 at 23:29
  • @user3288447 Because that doesn't make a copy of the array. I highly recommend reading the tutorials, or a good beginner's book on java. – Brian Roach Feb 08 '14 at 23:30
  • Use `Arrays#copyOf(yourArrayVar, yourArrayVar.length);` – Luiggi Mendoza Feb 08 '14 at 23:31
  • 1
    `int[] temp=test` does not create a new array object, it merely copies the array reference (ie, pointer) from "test" to "temp". – Hot Licks Feb 08 '14 at 23:58

2 Answers2

19

An array in Java is an object. When you create an array via new, it's created on the heap and a reference value (analogous to a pointer in C) is returned and assigned to your variable.

In C, this would be expressed as:

int *array = malloc(10 * sizeof(int));

When you pass that variable to a method, you're passing the reference value which is assigned (copied) to the local (stack) variable in the method. The contents of the array aren't being copied, only the reference value. Again, just like passing a pointer to a function in C.

So, when you modify the array in your method via that reference, you're modifying the single array object that exists on the heap.

You commented that you made a "copy" of the array via int[] temp=test ... again, this only makes a copy of the reference value (pointer) that points to the single array in memory. You now have three variables all holding the same reference to the same array (one in your main(), two in your method).

If you want to make a copy of the array's contents, Java provides a static method in the Arrays class:

int[] newArray = Arrays.copyOf(test, test.length); 

This allocates a new array object on the heap (of the size specified by the second argument), copies the contents of your existing array to it, then returns the reference to that new array to you.

Brian Roach
  • 76,169
  • 12
  • 136
  • 161
  • Say OP's `test` method instead contains `test = new int[] {7, 7, 7}`, essentially creating a new array and redirecting the pointer to that. Why is it that this time, the array outside is not changed? – user3932000 Apr 27 '17 at 02:23
4

Definitions:

  • Reference = A variable that points to the location in memory where your array lives.
  • Value of a Reference = The actual memory address location itself

You passed the value of the reference of your array into your test() method. Since java is Pass By Value, it passes the value of the reference, not the value of your array (ie. a copy).

It may be easier to think of a reference as a pointer if you have a C background. So a value of a reference is essentially it's memory address (I'm fudging java rules here but it may be simplest to think of it this way)

So, in your example, you pass the value of the reference which points to your array, into your test() method, which then uses that reference value to lookup where your array is in memory, so it can access data in your array.

Since in your test() method you do not change your array's reference (where it points to, ie. test = new int[10];), then your test() method acts on the original data in the array (because it still points to your original array's location), leading to element 0 being set to a value of 5.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
SnakeDoc
  • 13,611
  • 17
  • 65
  • 97