前言这是最近学习Java集合框架时做的一篇笔记主要记录了数组与ArrayList相互转换的底层原理和一些个人理解。内容比较基础算是对自己学习过程的一个梳理如果有不准确的地方欢迎指正一、数组转List1. 使用Arrays.asList()方法public static void testArray2List() { String[] strs {aaa, bbb, ccc}; ListString list Arrays.asList(strs); for (String s : list) { System.out.println(s); } }源码剖析Arrays.asList()方法的源码实现如下// Arrays 类中的方法 public static T ListT asList(T... a) { return new ArrayList(a);// 注意此 ArrayList 是 Arrays 的内部类 }这里返回的ArrayList并不是我们常用的java.util.ArrayList而是Arrays类内部的一个静态内部类// Arrays 的内部类不是 java.util.ArrayList private static class ArrayListE extends AbstractListE { private final E[] a; // 直接持有传入数组的引用 ArrayList(E[] array) { a array; // 没有拷贝直接存引用 } Override public E get(int index) { return a[index]; // 直接读原数组 } Override public E set(int index, E element) { E oldValue a[index]; a[index] element; // 直接改原数组 return oldValue; } // 没有重写 add() / remove() }关键点这个内部类ArrayList直接持有了原始数组的引用通过构造函数传入它没有实现add()、remove()等方法会抛出UnsupportedOperationException对List的修改会直接影响原始数组2. 转换后修改元素的影响修改List元素ListString list Arrays.asList(strs); list.set(0, ddd); // 合法操作 System.out.println(strs[0]); // 输出ddd原始数组也被修改修改数组元素strs[0] eee; System.out.println(list.get(0)); // 输出eeeList也被修改尝试添加/删除元素list.add(fff); // 抛出 UnsupportedOperationException list.remove(0); // 抛出 UnsupportedOperationException我的理解从源码可以看出几点它返回的根本不是java.util.ArrayList而是Arrays自己的一个内部类这个内部类直接继承自AbstractList。内部没有拷贝任何数据只是把原数组的引用存到了字段a里。get()和set()操作的都是这个字段a也就是直接操作原数组。所以本质上Arrays.asList()做的事情是给原数组套了一层List的壳让你可以以 List 的方式去读写原数组。这也解释了两个常见现象为什么不能add/remove —— 内部类没有重写这两个方法调用父类AbstractList的默认实现会直接抛UnsupportedOperationException而且数组长度本身就是固定的也没法真正加。为什么修改 List 元素会同步影响原数组 —— 因为本来就是同一块内存List 内部字段a指向的就是你传进来的那个数组对象。如果用一句话来概括Arrays.asList()返回的是一个零拷贝的数组视图不是一个真正的动态数组。如果你需要一个独立的、可修改的ArrayList标准写法是ListString list new ArrayList(Arrays.asList(array));这样会通过ArrayList的构造函数把数据拷贝一份得到一个真正属于自己的容器。二、List转数组1. 使用toArray()方法public static void testList2Array() { ListString list new ArrayListString(); list.add(aaa); list.add(bbb); list.add(ccc); String[] array list.toArray(new String[list.size()]); for (String s : array) { System.out.println(s); } }源码剖析ArrayList.toArray()方法的源码实现public T T[] toArray(T[] a) { if (a.length size) return (T[]) Arrays.copyOf(elementData, size, a.getClass()); System.arraycopy(elementData, 0, a, 0, size); if (a.length size) a[size] null; return a; }Arrays.copyOf()和System.arraycopy()做的事情可以概括为创建一个新的数组对象容器是新的把原 List 内部数组中的每个元素引用逐个拷贝到新数组中元素引用是旧的关键点toArray()方法会创建一个新的数组即使传入的数组长度足够也会复制元素新数组与原List是完全独立的互不影响传入的数组参数主要用于指定返回数组的类型2. 转换后修改元素的影响修改List元素ListString list new ArrayList(); list.add(aaa); String[] array list.toArray(new String[0]); list.set(0, bbb); System.out.println(array[0]); // 输出aaa数组不受影响修改数组元素array[0] ccc; System.out.println(list.get(0)); // 输出aaaList不受影响我的理解容器层面新数组是独立new出来的所以往新数组里赋值一个新元素array[0] new String(X)不会影响原 List。元素层面拷贝的只是引用地址如果元素是可变对象通过任意一端修改对象的属性另一端也会看到变化。这就是浅拷贝的语义。基本类型数组int[]、long[]等因为直接拷贝值不存在引用共享的问题天然就是完全独立的。三、完整示例与验证import java.util.*; public class ArrayToListConversion { // 数组转List public static void testArray2List() { System.out.println( 数组转List ); String[] strs {aaa, bbb, ccc}; ListString list Arrays.asList(strs); // 打印原始数组 System.out.println(原始数组: Arrays.toString(strs)); // 修改List元素 list.set(0, ddd); System.out.println(修改List后数组: Arrays.toString(strs)); // 修改数组元素 strs[1] eee; System.out.println(修改数组后List: list); // 尝试添加元素 try { list.add(fff); } catch (UnsupportedOperationException e) { System.out.println(添加元素失败: e.getMessage()); } } // List转数组 public static void testList2Array() { System.out.println(\n List转数组 ); ListString list new ArrayList(); list.add(aaa); list.add(bbb); list.add(ccc); // 转换为数组 String[] array list.toArray(new String[0]); // 打印原始List System.out.println(原始List: list); // 修改List元素 list.set(0, ddd); System.out.println(修改List后数组: Arrays.toString(array)); // 修改数组元素 array[1] eee; System.out.println(修改数组后List: list); } public static void main(String[] args) { testArray2List(); testList2Array(); } }输出结果 数组转List 原始数组: [aaa, bbb, ccc] 修改List后数组: [ddd, bbb, ccc] 修改数组后List: [ddd, eee, ccc] 添加元素失败: Unsupported operation List转数组 原始List: [aaa, bbb, ccc] 修改List后数组: [aaa, bbb, ccc] 修改数组后List: [ddd, bbb, ccc]四、关键结论数组转List (Arrays.asList())返回的List是原始数组的视图共享同一内存空间对List的修改会直接影响原始数组对数组的修改也会影响List不支持添加/删除操作会抛出UnsupportedOperationExceptionList转数组 (toArray())返回一个全新的数组与原始List完全独立对List的修改不会影响数组对数组的修改也不会影响List推荐使用list.toArray(new T[0])方式Java 6中性能更好使用建议如果需要一个可修改大小的List应将Arrays.asList()的结果包装进new ArrayList()如果需要完全独立的数组应使用toArray()方法在处理基本类型数组时需特别注意基本类型数组转List有特殊处理理解这些转换机制和相互影响关系对于编写健壮的Java代码非常重要特别是在处理集合和数组混合使用的场景时。写在最后以上就是这次关于数组与ArrayList转换的学习记录。后续我还会继续整理深浅拷贝、基本类型数组转换等其他相关话题慢慢补全这个系列。如果文中有理解偏差的地方欢迎大家在评论区交流指正