Java UnsupportedOperationException
An UnsupportedOperationException is thrown when an operation is performed on an object that does not support it. It is most commonly encountered with collections — particularly unmodifiable or fixed-size lists returned by factory methods like Arrays.asList(), List.of(), or Collections.unmodifiableList().
Common Causes
// Cause 1: Trying to add to Arrays.asList() result
List<String> list = Arrays.asList("a", "b");
list.add("c"); // UnsupportedOperationException
// Cause 2: Trying to add to List.of() (Java 9+ immutable)
List<String> immutable = List.of("x", "y");
immutable.add("z"); // UnsupportedOperationException
// Cause 3: Trying to modify an unmodifiable wrapper
List<String> wrapped = Collections.unmodifiableList(new ArrayList<>());
wrapped.add("item"); // UnsupportedOperationException
// Cause 4: Calling reduce on a Stream without identity
Stream<Integer> stream = Stream.of(1, 2, 3);
stream.reduce((a, b) -> a + b).get(); // works, but reduce on parallel
// streams may throw if no combiner
Solutions
Fix 1: Use a mutable collection type from the start
// Wrong — Arrays.asList returns a fixed-size list
List<String> list = Arrays.asList("a", "b");
list.add("c"); // UnsupportedOperationException
// Correct — wrap in ArrayList for full mutability
List<String> list = new ArrayList<>(Arrays.asList("a", "b"));
list.add("c"); // works fine
// Correct — build with List.of then wrap (Java 9+)
List<String> list = new ArrayList<>(List.of("a", "b"));
list.add("c");
Fix 2: Understand what each factory method returns
// Fixed-size list — can set(), but not add()/remove()
List<String> fixed = Arrays.asList("a", "b");
fixed.set(0, "x"); // works
fixed.add("c"); // UnsupportedOperationException
// Truly immutable — cannot modify at all
List<String> immutable = List.of("a", "b");
immutable.set(0, "x"); // UnsupportedOperationException
immutable.add("c"); // UnsupportedOperationException
Fix 3: Copy unmodifiable collections before modifying
List<String> config = Collections.unmodifiableList(getConfigValues());
// Wrong — modifying the unmodifiable wrapper
config.add("extra");
// Correct — copy to a mutable list first
List<String> mutableConfig = new ArrayList<>(config);
mutableConfig.add("extra");
Fix 4: Implement the method if you extend an abstract class
import java.util.AbstractList;
public class SinglyLinkedList<E> extends AbstractList<E> {
private final List<E> data = new ArrayList<>();
@Override
public E get(int index) {
return data.get(index);
}
@Override
public int size() {
return data.size();
}
// Optional: override add() if you want add() to work
@Override
public boolean add(E element) {
return data.add(element);
}
}
// Without overriding add(), add() throws UnsupportedOperationException
Fix 5: Use List.copyOf() for truly immutable snapshots (Java 10+)
List<String> mutable = new ArrayList<>(Arrays.asList("a", "b"));
List<String> snapshot = List.copyOf(mutable);
// snapshot is immutable — no mutation methods work
// Use this when you intentionally want an unmodifiable view
Prevention Tips
- Know the difference between
Arrays.asList()(fixed-size),List.of()(immutable), andnew ArrayList<>()(mutable) - When returning collections from methods, decide intentionally whether callers should be able to modify them
- Document whether your method returns an unmodifiable view or a copy
- Use
Collections.unmodifiableList()when exposing internal state to prevent accidental modification
Related Errors
- NullPointerException — null reference access
- IllegalArgumentException — invalid method argument
- IndexOutOfBoundsException — out of bounds access
Comments