I'm afraid the answer is yes.
Note that Collections.unmodifiableCollection only returns a view. Essentially, Collections contains an adapter class which takes in any Collection
and forwards certain method calls to it. For the 'dangerous' methods, it throws an exception instead. This relies on the underlying collection passed in to implement things in a sane manner of course. If getSize()
mutates the object, then calling getSize()
on the adapter will still forward it to the underlying class, which is then modified.
You can reduce the amount of work by limiting the number of different classes (or interfaces) you return to clients. You can also make more of your classes immutable by default, a common paradigm in functional languages which makes things much simpler. Unfortunately, Java makes working with immutable objects unnecessarily ugly.
There are also possibilities like generating the immutable views automatically, but that's complicated and requires you to have a way of deciding which methods to forward anyway.
Lastly, none of this protects you from setAccessible
or the like. But in that case, they're deliberately violating the standard VM constraints, so it's not really something you should worry about. If you're worried about security, you'll need to run all untrusted code in a SecurityManager anyway.