为何修改Arrays.asList传入的数组会同步改变返回的List?
为什么
Arrays.asList()返回的List会随原数组变化? 这问题我刚学Java的时候也踩过坑,其实核心点在于:你看到的new ArrayList<>()根本不是java.util.ArrayList!
拆解源码里的猫腻
咱们看Arrays.asList()的源码:
@SafeVarargs @SuppressWarnings("varargs") public static <T> List<T> asList(T... a) { return new ArrayList<>(a); }
这里的ArrayList是java.util.Arrays类的私有内部类,不是咱们平时用的那个顶层java.util.ArrayList。咱们看看这个内部类的核心实现(简化版):
private static class ArrayList<E> extends AbstractList<E> implements RandomAccess, java.io.Serializable { private final E[] a; ArrayList(E[] array) { a = array; // 直接持有原数组的引用,没有复制! } // 其他方法比如get、set都是直接操作这个数组a }
看到没?这个内部类直接把传入的数组赋值给自己的成员变量a,完全没有做数组拷贝。所以当你修改原数组的时候,这个内部类持有的数组引用指向的是同一个对象,自然List的内容会跟着变。
你的示例验证了这个逻辑
咱们看你贴的测试代码:
public class Test { public static void main(String[] args) { Integer [] array = {1,2,3,4,5}; List<Integer> list = Arrays.asList(array); System.out.println("List created from array: " + list); array[0] = 100; System.out.println("List after changing array:" + list); } }
运行输出:
List created from array: [1, 2, 3, 4, 5] List after changing array:[100, 2, 3, 4, 5]
因为list内部持有的就是array的引用,所以修改array[0]本质上就是修改了list底层的数组内容。
怎么避免这个问题?
如果想让List和原数组完全独立,需要手动创建一个真正的java.util.ArrayList,把Arrays.asList()的结果传进去,这时候会做数组拷贝:
List<Integer> independentList = new ArrayList<>(Arrays.asList(array));
或者用Java 8+的Stream来实现:
List<Integer> independentList = Arrays.stream(array).collect(Collectors.toList());
这样修改原数组就不会影响到新的List了。
内容的提问来源于stack exchange,提问作者Sivaram Chintalapudi
相关产品推荐
相关产品推荐

