3
import java.util.*;

public class Test {
    public static void main(String[] args) {
        String[] arr = {"Java", "Champ", "."};
        List<String> list = (List<String>) Arrays.asList(arr); // line 1
        arr[2] = ".com"; // line 2
        for (String word : list) {
            System.out.print(word);
        }
    }
}

Can please someone explain me why we get here "JavaChamp.com"? I thought it shoud be just "JavaChamp." because line 2 after line 1.

Aniket Sahrawat
  • 12,410
  • 3
  • 41
  • 67
Vlad Starostenko
  • 121
  • 1
  • 10

2 Answers2

5

Because Arrays#asList returns the fixed-size List backed by the array.

Here is the doc of Arrays#asList:

Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray(). The returned list is serializable and implements RandomAccess.

Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
Aniket Sahrawat
  • 12,410
  • 3
  • 41
  • 67
  • Related: [How to prevent changing the value of variable](https://stackoverflow.com/questions/55428172/how-to-prevent-changing-the-value-of-variable) – Aniket Sahrawat Oct 11 '19 at 01:59
1

You can actually take a look at the code if you want to understand what's happening. In your case, let's take a look at java.util.Arrays#asList(T...)

@SafeVarargs
public static <T> List<T> asList(T... var0) {
    return new Arrays.ArrayList(var0); // notice this
}

It returns an inner class called 'ArrayList' (not to be confused with java.util.ArrayList, these are different classes, but they do more or less the same thing).

// the inner class
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, Serializable {
    private final E[] a;

    ArrayList(E[] var1) {
        this.a = Objects.requireNonNull(var1); // directly reuses the array you pass in
    }
}

Based on this code, we see that the array is reused. It's also important to note that Java will pass arrays as is rather than as a copy in parameters. What does that mean?

int[] arr = { 1, 2, 3, 4, 5 };
modifyArray(arr);
assert arr[0] == 2; // true

void modifyArray(int[] array) {
    array[0] = 2;
}

Due to this, we can confirm we will share the array instance across parameters. For that reason, when you mutate the array from your scope, you are indirectly affecting the backing array for Arrays$ArrayList.

Frontear
  • 1,150
  • 12
  • 25
  • 1
    "pass ... as is" and "copy in parameters" are usually called [_call/pass by reference_](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_reference) and [_call/pass by value_](https://en.wikipedia.org/wiki/Evaluation_strategy#Call_by_value). – Gerold Broser Oct 19 '19 at 00:34