A quite undocumented Java quirk struck me last week regarding the serialization of java.util.List objects. The lists are normally serializable and just dump their object content nicely into the output. Little is it known that List.subList() does not produce a list of the same type as the original, but instead a RandomAccessSubList. In the documentation, this list is simply called a ”view”.
In shorter words, here is a serialization (XStream) and output of an ArrayList containing some integers:
List<Integer> list = new ArrayList<Integer>(); list.add(1); list.add(2); list.add(3); System.out.println(serializer.toXML(list));
<list id="1"> <int>1</int> <int>2</int> <int>3</int> </list>
Here is the same procedure but using a sublist:
list = list.subList(0, 3);
<java.util.RandomAccessSubList id="1">
<l class="list" id="2">
<int>1</int>
<int>2</int>
<int>3</int>
</l>
<offset>0</offset>
<size>3</size>
<expectedModCount>3</expectedModCount>
</java.util.RandomAccessSubList>
This view-wrapped list plays nicely and is not noticable in most cases. However, if you save this serialization for later use, the mod count will get saved with it. Tampering the unmarshalled list at a later time will produce a rather surprising ConcurrentModificationException.
The moral of this story is to always wrap calls to List.subList() in another container, which implicitly calls addAll().
End transmission.


