# 22. 为什么 Arrays.asList()
生成的 List
不能进行 add/remove
操作?
# 标准答案
Arrays.asList()
生成的 List
本质上是 java.util.Arrays.ArrayList
(内部类),它并不是 java.util.ArrayList
,而是基于数组的固定大小 List
。该 List
仅是原数组的视图(View),不支持增删元素,但支持修改已有元素。
这背后的原因是:
Arrays.asList()
直接使用原数组作为底层存储,无法动态扩展或收缩。add()
/remove()
需要调整内部存储(如扩容或缩容),但Arrays.ArrayList
只是包装了原数组,无法真正改变数组大小,因此抛出UnsupportedOperationException
。
如果需要支持增删操作,应使用 new ArrayList<>(Arrays.asList(...))
进行拷贝。
# 答案解析
# 1. Arrays.asList()
返回的 List
实现类
List<Integer> list = Arrays.asList(1, 2, 3);
System.out.println(list.getClass()); // class java.util.Arrays$ArrayList
1
2
2
Arrays.asList()
返回的是 java.util.Arrays.ArrayList
(内部类),而不是 java.util.ArrayList
。
# 2. 为什么 add/remove
会抛异常?
执行以下代码:
List<Integer> list = Arrays.asList(1, 2, 3);
list.add(4); // UnsupportedOperationException
list.remove(1); // UnsupportedOperationException
1
2
3
2
3
会抛出:
Exception in thread "main" java.lang.UnsupportedOperationException
1
原因是 ArrayList
(Arrays.ArrayList
的内部类)没有实现 add()
和 remove()
,其 size
直接来自底层数组,数组大小固定,无法增删。
# 3. Arrays.ArrayList
内部结构
源码(JDK 8):
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable {
final E[] a; // 持有的数组
ArrayList(E[] array) {
a = Objects.requireNonNull(array);
}
public E get(int index) {
return a[index]; // 直接访问数组
}
public E set(int index, E element) {
E oldValue = a[index];
a[index] = element; // 允许修改原数组
return oldValue;
}
public int size() {
return a.length; // 大小固定
}
public void add(int index, E element) {
throw new UnsupportedOperationException(); // 不支持插入
}
public E remove(int index) {
throw new UnsupportedOperationException(); // 不支持删除
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
可以看到:
get()
直接访问a[index]
,允许读取set()
直接修改a[index]
,允许修改add()
/remove()
直接抛出UnsupportedOperationException
,不允许增删
# 4. 如何正确使用 Arrays.asList()
?
# 方法 1:用 new ArrayList<>()
复制
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3));
list.add(4); // 可正常添加
System.out.println(list); // [1, 2, 3, 4]
1
2
3
2
3
# 方法 2:使用 List.of()
(JDK 9+,不可变)
List<Integer> list = List.of(1, 2, 3);
list.add(4); // UnsupportedOperationException
1
2
2
List.of()
生成的 List
完全不可变,set()
也不允许。
# 方法 3:使用 ArrayList.copyOf()
(JDK 10+,不可变)
List<Integer> list = List.copyOf(Arrays.asList(1, 2, 3));
1
返回的 List
也是不可变的,避免误用。
# 深入追问
Arrays.asList()
与List.of()
在不可变性上有何不同?- 为什么
set()
允许,但add()
/remove()
不允许? Arrays.asList()
为什么不会影响原数组?
# 相关面试题
List.of()
和Arrays.asList()
的区别?Collections.unmodifiableList()
和List.copyOf()
的区别?- 为什么
Arrays.asList()
返回的List
不能序列化?