首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Arrays.asList 源碼深度解析:為什麼返回的 List 不支持增刪?

     編輯:Java 綜合教學

現象回顧

List<String> list = Arrays.asList("a", "b"); list.add("c"); // 拋出 UnsupportedOperationException

很多開發者初次遇到此問題感到困惑。本文從源碼層面徹底講透原因。

源碼層層剝離

1. Arrays.asList 入口

@SafeVarargs
public static <T> List<T> asList(T... a) {
    return new ArrayList<>(a); // 注意:這不是 java.util.ArrayList!
}

2. 內部私有類 Arrays.ArrayList

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable {
    private static final long serialVersionUID = -2764017481108945198L;
    private final E[] a; // 底層數組,final 不可變引用

    ArrayList(E[] array) {
        if (array == null) throw new NullPointerException();
        a = array; // 直接引用傳入數組,無拷貝
    }

    public E get(int index) { return a[index]; }
    public E set(int index, E element) {
        E old = a[index];
        a[index] = element;
        return old;
    }
    // 沒有 add/remove 方法!
}

關鍵點:

  • 繼承 AbstractList,而非 java.util.ArrayList
  • 底層數組 final E[] a,長度固定
  • 僅實現 get/set,無 add/remove

3. 父類 AbstractList 的默認實現

public void add(int index, E element) {
    throw new UnsupportedOperationException();
}
public E remove(int index) {
    throw new UnsupportedOperationException();
}

這些「可選操作」默認拋異常。設計意圖:避免所有子類都要實現一堆無意義的方法。若改為抽象方法,每個子類都得重寫,極其繁瑣;採用「默認拋異常 + 文檔標註可選」,子類只需覆寫自己支持的操作。

為什麼這樣設計?

  1. 性能優先:直接包裝原數組,零拷貝、零額外內存
  2. 語義清晰:asList 即「作為 List 視圖」,非「轉換為可變 List」
  3. 接口隔離:List 接口包含可變/不可變操作,AbstractList 以「可選操作」模式平衡擴展性與簡潔性

正確獲取可變 List 的姿勢

// 方式一:拷貝構造
List<String> mutable = new ArrayList<>(Arrays.asList("a", "b"));
mutable.add("c"); // OK

// 方式二:Java 9+ List.of + 拷貝
List<String> mutable = new ArrayList<>(List.of("a", "b"));

// 方式三:Stream 收集
List<String> mutable = Stream.of("a", "b").collect(Collectors.toList());

總結

Arrays.asList 返回的是 固定大小、底層共享數組的 List 視圖,僅支持 get/set/contains 等只讀/替換操作。需增刪時,請顯式拷貝至 java.util.ArrayList。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved