List<String> words = Arrays.asList("i", "love", "you");
words.remove("love"); // 拋出 java.lang.UnsupportedOperationException
許多開發者直覺以為 Arrays.asList() 返回標準的 java.util.ArrayList,支持增刪改查。實際運行卻拋出異常,原因在於它返回的是 java.util.Arrays 內部的一個 私有靜態類 ArrayList,而非 java.util.ArrayList。
// JDK 源碼簡化版
private static class ArrayList<E> extends AbstractList<E>
implements RandomAccess, java.io.Serializable {
private final E[] a; // 底層引用外部傳入的數組,final 不可變
ArrayList(E[] array) { a = Objects.requireNonNull(array); }
@Override public int size() { return a.length; }
@Override public E get(int index) { return a[index]; }
@Override public E set(int index, E element) { // 僅支持替換
E old = a[index];
a[index] = element;
return old;
}
// **關鍵點:沒有重寫 remove/add 方法,繼承自 AbstractList**
}
public E remove(int index) {
throw new UnsupportedOperationException(); // 直接拋異常
}
public boolean add(E e) {
add(size(), e); // 拋異常
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
因此,Arrays.ArrayList 具有 固定長度 特性:支持 get、set、contains、indexOf 等只讀操作,但 不支持任何結構性修改(add/remove/clear)。
transient Object[] elementData。List 接口,支持擴容、插入、刪除。Arrays.asList(T... a) 的初衷是 「將數組快速包裝為 List 視圖」,以便使用集合框架的豐富 API(如流式操作、遍歷、查找),而非創建獨立可變副本。這種「視圖模式」避免了數組拷貝,性能極高,但也意味著:
// 直接使用,零拷貝,高性能
List<String> words = Arrays.asList("apple", "banana", "orange");
words.stream().filter(s -> s.startsWith("a")).forEach(System.out::println);
// 方案 A:手動拷貝到新 ArrayList(推薦,語義清晰)
List<String> mutableList = new ArrayList<>(Arrays.asList("a", "b", "c"));
mutableList.add("d"); // OK
// 方案 B:Java 9+ List.of() + new ArrayList()(不可變列表轉可變)
List<String> list = new ArrayList<>(List.of("a", "b", "c"));
// 方案 C:Guava Lists.newArrayList()(第三方庫)
// List<String> list = Lists.newArrayList("a", "b", "c");
// Java 9+ 便利工廠方法(返回不可變列表)
List<String> immutable = List.of("a", "b", "c"); // 不可變,線程安全
// List<String> mutable = new ArrayList<>(List.of("a", "b", "c")); // 需可變時再拷貝
| 操作 | Arrays.asList() 返回列表 | new ArrayList<>(...) |
|---|---|---|
| get / set / contains / indexOf | ✅ 支持 | ✅ 支持 |
| add / remove / clear | ❌ 拋異常 | ✅ 支持 |
| 修改元素內容 (set) | ✅ 影響原數組 | ✅ 僅影響列表 |
| 序列化 | ✅ 支持 | ✅ 支持 |
| 線程安全 | ❌ 非線程安全 | ❌ 非線程安全 |
Arrays.asList() 返回的是 java.util.Arrays.ArrayList —— 一個 固定長度、底層共享數組、不支持結構修改 的 List 視圖。它不是 java.util.ArrayList。遇到 UnsupportedOperationException 時,請檢查是否誤將其當作可變列表使用。需要增刪改時,請顯式拷貝 new ArrayList<>(Arrays.asList(...)) 或使用 Java 9+ List.of() + 拷貝模式。理解「視圖」與「副本」的區別,是避開此坑的關鍵。