The way to achieve immutability is to create defensive copies.
Data in
Whenever a mutable object is passed to your method(s), you create a deep copy of it. This should be the first thing you do, even before you check validity, if you want maximum security.
Wrapping a list into a Collections.unmodifiableList()
isn't going to work here because there's no guarantee that the underlying list won't be modified by a third party. In other words, you're not in control of the instance.
A good way of creating immutable copies of lists is by using Google Guava's ImmutableList.copyOf()
method, but remember that you need a deep copy, so you need to create immutable copies of the lists within the main list.
Data out
whenever you return a value, you make another defensive copy, so that changes to the returned object don't reflect back. Here you can use unmodifiable wrappers (e.g. ImmutableList.of()
) on your lists because you're holding the only reference to the original list.
If you do both (copy on the way in, copy/wrap on the way out), your code will be safe and correct. Any other solution and no such general guarantees can be given, your code may or many not be correct.