Cách khắc phục java.lang.UnsupportedOperationException trong Java List

beginner Java2026-05-01| Java Development Kit (JDK) 8, 11, 17, 21+ trên bất kỳ hệ điều hành nào (Windows, macOS, Linux)

Error Message

java.lang.UnsupportedOperationException
#java#collections#danh-sach#unsupportedoperationexception

TL;DR: Cách khắc phục nhanh

Lỗi java.lang.UnsupportedOperationException thường xảy ra do bạn đang cố gắng thêm hoặc xóa các phần tử khỏi một danh sách có kích thước cố định hoặc không thể thay đổi (immutable). Cách nhanh nhất để khắc phục là bao bọc danh sách hiện có của bạn trong một ArrayList mới.

// Thay vì làm thế này (ném ra ngoại lệ khi thay đổi):
List<String> list = Arrays.asList("A", "B", "C");

// Hãy làm thế này (tạo một bản sao có thể thay đổi):
List<String> mutableList = new ArrayList<>(Arrays.asList("A", "B", "C"));
mutableList.add("D"); // Bây giờ nó đã hoạt động!

Xác định nguyên nhân gốc rễ

Trong Java, không phải tất cả các danh sách đều được tạo ra như nhau. Mặc dù tất cả chúng đều triển khai interface List, nhưng cấu trúc bên dưới của chúng sẽ quyết định việc bạn có thể sửa đổi chúng hay không. Lỗi java.lang.UnsupportedOperationException được ném ra khi bạn gọi một phương thức (như add(), remove(), hoặc clear()) mà việc triển khai danh sách cụ thể đó không hỗ trợ.

Nguyên nhân phổ biến 1: Arrays.asList()

Khi bạn sử dụng Arrays.asList("item1", "item2"), nó trả về một danh sách có kích thước cố định. Danh sách này được hỗ trợ bởi mảng gốc. Bạn có thể thay đổi giá trị của một phần tử hiện có bằng set(), nhưng bạn không thể thay đổi kích thước của danh sách. Vì add()remove() sẽ làm thay đổi kích thước, chúng sẽ ném ra ngoại lệ.

List<String> items = Arrays.asList("Apple", "Banana");
items.set(0, "Apricot"); // Lệnh này ổn
items.add("Cherry");    // Ném ra java.lang.UnsupportedOperationException

Nguyên nhân phổ biến 2: List.of() (Java 9 trở lên)

Được giới thiệu từ Java 9, List.of() tạo ra một danh sách thực sự không thể thay đổi (immutable). Khác với Arrays.asList(), bạn thậm chí không thể sử dụng set() để thay đổi giá trị hiện có. Bất kỳ nỗ lực nào nhằm thay đổi danh sách theo bất kỳ cách nào đều dẫn đến lỗi.

List<String> items = List.of("Apple", "Banana");
items.set(0, "Orange"); // Ném ra java.lang.UnsupportedOperationException
items.add("Cherry");    // Ném ra java.lang.UnsupportedOperationException

Nguyên nhân phổ biến 3: Collections.unmodifiableList()

Đôi khi bạn nhận được một danh sách từ một thư viện hoặc một phần khác trong mã nguồn đã được bao bọc để ngăn chặn việc sửa đổi. Đây là một mô hình phổ biến để bảo vệ các cấu trúc dữ liệu nội bộ.

Các cách khắc phục hiệu quả

1. Tạo một bản sao có thể thay đổi (Khuyên dùng)

Giải pháp mạnh mẽ nhất là truyền danh sách cố định hoặc không thể thay đổi vào hàm khởi tạo của java.util.ArrayList. Điều này tạo ra một danh sách hoàn toàn mới chứa các phần tử tương tự, nhưng với đầy đủ chức năng của một mảng động tiêu chuẩn.

List<String> fixedList = Arrays.asList("one", "two");
List<String> workingList = new ArrayList<>(fixedList);

workingList.add("three");
workingList.remove("one");

2. Sử dụng Java 8 Stream API

Nếu bạn đang xử lý dữ liệu bằng stream và muốn đảm bảo danh sách kết quả có thể thay đổi, hãy sử dụng Collectors.toCollection(ArrayList::new) thay vì Collectors.toList() mặc định (trong một số phiên bản Java hoặc cách triển khai, nó có thể trả về một danh sách không thể thay đổi).

List<String> mutableList = someDataSource.stream()
    .filter(s -> s.startsWith("A"))
    .collect(Collectors.toCollection(ArrayList::new));

3. Khởi tạo đúng cách cho Java 7 và cũ hơn

Nếu bạn không sử dụng các phương thức hỗ trợ hiện đại, hãy tuân thủ cách khởi tạo cổ điển để tránh những bất ngờ:

List<String> list = new ArrayList<String>();
list.add("A");
list.add("B");

Các bước xác minh

Để xác nhận bản sửa lỗi của bạn đang hoạt động, hãy thực hiện một bài kiểm tra sửa đổi đơn giản ngay sau khi tạo danh sách. Nếu đoạn mã sau thực thi mà không gặp lỗi, danh sách của bạn đã có thể thay đổi:

try {
    List<String> myTestList = // ... logic tạo danh sách của bạn
    myTestList.add("test_element");
    myTestList.remove("test_element");
    System.out.println("Thành công: Danh sách có thể thay đổi.");
} catch (UnsupportedOperationException e) {
    System.err.println("Thất bại: Danh sách vẫn không thể thay đổi hoặc có kích thước cố định!");
}

Những điểm chính cần lưu ý

- **Arrays.asList** có kích thước cố định (hỗ trợ `set`, nhưng không hỗ trợ `add/remove`).
- **List.of** là bất biến nghiêm ngặt (không hỗ trợ bất kỳ thay đổi nào).
- Hàm khởi tạo **ArrayList** là lựa chọn tốt nhất để chuyển đổi các danh sách bị hạn chế thành danh sách có thể làm việc được.
- Luôn kiểm tra tài liệu của các API bên thứ ba để xem các danh sách mà chúng trả về có được phép sửa đổi hay không.

Related Error Notes