You are currently viewing How to Fix UnsupportedOperationException In Java

How to Fix UnsupportedOperationException In Java

1. Introduction

If you have written programs that use the collection API, there is a good chance that you have already encountered the UnsupportedOperationException. This article will guide you through resolving this exception and provide best practices to prevent it.

2. What Java Says about UnsupportedOperationException

According to the Javadoc, an UnsupportedOperationException is thrown to indicate that the requested operation is not supported.

3. How to Reproduce UnsupportedOperationException

The UnsupportedOperationException is a member of the Java Collections Framework. Java will throw this exception whenever you try to perform an operation on a collection that does not have support for such an operation. A typical situation is when you attempt to add or remove an element from an unmodifiable collection.
Many factory methods in Java return unmodifiable collections. We will focus on some of the common use cases.

3.1 Using List.of()

This factory method introduced in Java 9 is used when you want to create a list directly from a set of static values. The method returns an unmodifiable list. Hence, any attempt to add a new element (or remove) will result in an UnsupportedOperationException.

        List<String> unmodifiableList = List.of("hello");
        unmodifiableList.add("world");//UnsupportedOperationException

Output:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
    at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:147)
    at Scratch.main(scratch_2.java:8)

To fix this, you should either not mutate the object’s state or create it differently so it won’t be immutable. Here is a simple way to create a mutable list using the default constructor of the ArrayList class:

        List<String> mutableList = new ArrayList<>();
        mutableList.add("hello");//No UnsupportedOperationException
        mutableList.add("world");//No UnsupportedOperationException

3.2 Using Stream#toList()

Java 16 introduced a simpler way to collect the result of a Stream into a List. However, this new ternary operation from the Stream API returns an unmodifiable list:

        List<String> list = new ArrayList<>();
        list.add("hello");
        List<String> unmodifiableList = list.stream().toList();

If you attempt to add a new item to the resulting list unmodifiableList, an UnsupportedOperationException will be thrown:

        unmodifiableList.add("world");//UnsupportedOperationException

Output:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.ImmutableCollections.uoe(ImmutableCollections.java:142)
    at java.base/java.util.ImmutableCollections$AbstractImmutableCollection.add(ImmutableCollections.java:147)
    at Scratch.main(scratch_2.java:21)

To fix this exception, you should ensure the returned list is immutable. One way to achieve that is by using the Stream#collect(Collectors.toList()) method which returns a modifiable list.

        List<String> list = new ArrayList<>();
        list.add("hello");
        List<String> modifiableList = list.stream().collect(Collectors.toList());
        modifiableList.add("world");//No UnsupportedOperationException

3.3 Using Arrays.asList()

This factory method is commonly used to convert an array into an ArrayList. You should be aware that the method returns a fixed-size ArrayList. If you call any method that would change the size of the resulting list, Java will throw an UnsupportedOperationException.

        String[] myArray = {"hello"};
        List<String> fixedSizeList = Arrays.asList(myArray);
        fixedSizeList.add("world");//UnsupportedOperationException

Output:

Exception in thread "main" java.lang.UnsupportedOperationException
    at java.base/java.util.AbstractList.add(AbstractList.java:153)
    at java.base/java.util.AbstractList.add(AbstractList.java:111)
    at Scratch.main(scratch_2.java:10)

The solution here is to make sure that any method you call on the resulting list does not affect the ArrayList size. However, if you need to mutate the size of the List, then you should not use the Arrays.asList() utility method.

        String[] myArray = {"hello"};
        List<String> fixedSizeList = Arrays.asList(myArray);
        fixedSizeList.set(0,"world");//No UnsupportedOperationException

4. Best Practices to Avoid UnsupportedOperationException

4.1. Know Your Collections

Understand the characteristics and capabilities of the collections you are working with. Be aware of which operations are supported and which are not, especially when dealing with collections obtained from utility methods. If you have any doubts, always refer to the official Javadoc.

4.2. Use immutable collections when appropriate

If you do not want others to mutate the state of your collection after its creation, consider using an immutable collection or Wrappers like Collections.unmodifiableXXX() to prevent accidental modifications.
As an example, let’s assume we have a Student class with an attribute List<Course> courses. Here is the correct way to implement the getter for this field:

    public List<Course> getCourses(){
        return Collections.unmodifiableList(this.courses);//Don't just return this.courses
    }

This ensures that clients of the Student class cannot modify the list of courses directly, maintaining encapsulation and preventing unintended modifications.

5. Conclusion

In this brief tutorial, you learned about the UnsupportedOperationException and how to fix it.

You can find the complete code of this article here in GitHub

Noel Kamphoa

Experienced software engineer with expertise in Telecom, Payroll, and Banking. Now Senior Software Engineer at Societe Generale Paris.