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.
List.of()
3.1 Using 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
Stream#toList()
3.2 Using 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
Arrays.asList()
3.3 Using 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.
Originally published at https://nkamphoa.com
Hi Noel,
Thanks a ton for sharing your expertise on fixing the UnsupportedOperationException in Java. Your clear explanation and step-by-step guide were incredibly helpful in understanding the issue and implementing the solution effectively.
I’ve successfully applied your recommendations and the issue seems to be resolved now. Your article has been a lifesaver!
Looking forward to more insightful content from you in the future.
Best regards