Do Arrays in Java Violate “Call by Value”?
Tags: java, arrays, methods
Published: 2022-03-23 16:28:13

> “Any headline that ends in a question mark can be answered by the word ‘no’.”
> -- Betteridge’s Law of Headlines

When you first learned about methods in Java, you might have read something like “arguments are always passed to parameters by value.”  This means that a parameter is always a *copy* of the argument. You can change the value of the parameter all you want, and the original argument will remain unaffected. In this code:

```java
public class ByValue1 {
    public static void printCube(int n) {
        n = n * n * n;
        System.out.println("The cube is " + n);
    }

    public static void main(String[] args) {
        int n = 12;
        System.out.println("Before call, n is " + n);
        printCube(n);
        System.out.println("After call, n is " + n);
    }
}
```
The output shows that `n` in `main()` remains unchanged:
```
Before call, n is 12
The cube is 1728
After call, n is 12
```

This is a good thing; imagine calling `printCube(3);` you certainly wouldn’t want Java to change the literal 3 to 27!

Further along in your adventures with Java, you encountered arrays, and may have seen a program like this:

```java
import java.util.Arrays;

public class ByValue2 {
    public static void cubeArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * arr[i] * arr[i];
        }
    }

    public static void main(String[] args) {
        int [] data = {10, 2, 4};
        System.out.println("Before call, data is " +
           Arrays.toString(data));
        cubeArray(data);
        System.out.println("After call, data is " +
            Arrays.toString(data));
    }
}
```
When you run this program, you get this output:
```
Before call, data is [10, 2, 4]
After call, data is [1000, 8, 64]
```

What’s going on here? The array contents have changed! Is this an exception to “always call by value“?  No, it isn’t. The key point here is that *arrays are references*.  Here’s what a memory diagram looks like when we enter the `cubeArray` method:

![Two references to same area of memory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ixlhn67rxnc1ly6yky6k.png)

When doing the multplication `arr[i] * arr[i] * arr[i]`, Java is changing element `i` **in the memory that `arr` refers to**; it is *not* changing `arr` itself.  We can prove this by printing out the reference, which will show the memory address of the arrays:

```java
import java.util.Arrays;

public class ByValue3 {
    public static void cubeArray(int[] arr) {
        System.out.println("At start of cubeArray, arr is "
            + arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * arr[i] * arr[i];
        }
        System.out.println("At end of cubeArray, arr is "
            + arr);
    }

    public static void main(String[] args) {
        int [] data = {10, 2, 4};
        System.out.println("Before call, data is " +
            Arrays.toString(data) + " reference " + data);
        cubeArray(data);
        System.out.println("After call, data is " +
            Arrays.toString(data) + " reference " + data);
    }
}
```

When you print an array with `System.out.println`, you will get something like `[I@764c12b6`, which means you have an array (`[`) of integers (`I`) at memory location 764c12b6 (`@764c12b6`). Running the program shows that the references have never changed, but the **referred-to** array has:


```
Before call, data is [10, 2, 4] reference [I@764c12b6
At start of cubeArray, arr is [I@764c12b6
At end of cubeArray, arr is [I@764c12b6
After call, data is [1000, 8, 64] reference [I@764c12b6
```

So, in fact, this program doesn’t settle the question of call by value one way or the other, since nothing here has changed the reference `arr` itself.  Let’s put that to the test by doing something that *will* change `arr`&mdash;we’ll set `arr` to refer to a brand new array:

```java
public class ByValue4 {
    public static void cubeArray(int[] arr) {
        System.out.println("At start of cubeArray, arr is "
            + arr);
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * arr[i] * arr[i];
        }
        // make arr refer to a different area of memory
        arr = new int[4]; 
        System.out.println("At end of cubeArray, arr is "
            + arr);
    }

    public static void main(String[] args) {
        int [] data = {10, 2, 4};
        System.out.println("Before call, data is " +
            Arrays.toString(data) + " reference " + data);
        cubeArray(data);
        System.out.println("After call, data is " +
            Arrays.toString(data) + " reference " + data);
    }
}
```

Here’s the memory diagram just before we leave `cubeArray()`:

![parameter refers to different area of memory](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/njhtzm7j9w5o8hlp9i0b.png)

If call by value really works everywhere, the reference to `data` in `main()` should not change.  Let’s see the output:

```
Before call, data is [10, 2, 4] reference [I@764c12b6
At start of cubeArray, arr is [I@764c12b6
At end of cubeArray, arr is [I@4e0e2f2a
After call, data is [1000, 8, 64] reference [I@764c12b6
```

The third line of the output shows that we changed the `arr` reference (the parameter) in the `cubeArray()` method, but the fourth line shows that the original `data` reference in `main()` was not affected. The *reference* is, indeed, passed by value.

Thus, the answer to the article headline: Do Arrays in Java Violate “Call by Value”? The answer is “no.“  Java is *always* call by value.