javalistimmutabilityinstanceof

Check if List is immutable


How to check type of implementation? How can you correct the last line so that it compiles and returns true?

List<String> list1 = new ArrayList<>(List.of("1", "2"));
List<String> list2 = List.of("1", "2").stream().toList();

list1 instanceof List<String>; // true

list2.getClass().getName(); // java.util.ImmutableCollections$ListN
list2 instanceof java.util.ImmutableCollections; // does not compile

Solution

  • For a List to be immutable, it is necessary (although not sufficient) for it to have implemented all of the methods marked "optional" in the Javadoc to simply throw an UnsupportedOperationException.

    There is no safe way to check whether this is the case - the only mechanism would be to invoke all of the methods; but at least some of these would necessarily mutate the list if they don't throw the exception; plus, this would only tell you whether the list is unmodifiable, which isn't the same as immutable.

    You could check for specific "known immutable" (or "known mutable") types using reflection (e.g. myList.getClass()....); but you can't hope to cover all List implementations like that, since there are infinitely many possible implementations. In other words, you could reflectively detect some classes that you definitely know either to be mutable or immutable; but you still don't know in general.

    You should in general assume that a List argument to a method doesn't implement any of the optional methods, because there is no way of testing whether those methods are "really" implemented or will throw an NotImplementedException.

    If you actually need a mutable list, you should either: