Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my List modified when I alter the array it was created from [duplicate]

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.

like image 785
Vlad Starostenko Avatar asked Nov 21 '25 02:11

Vlad Starostenko


2 Answers

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.

like image 106
Aniket Sahrawat Avatar answered Nov 22 '25 15:11

Aniket Sahrawat


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.

like image 23
Frontear Avatar answered Nov 22 '25 16:11

Frontear