I am working on implementing Joshua Bloch's Item 15 Minimize mutability, for classes that contain HashMaps and ArrayLists, for which I understand defensive copies need to be made to ensure that references to them to do not leak out through accessors.
So I suppose I am looking for the most efficient idiom to do this.
are these it?
when in doubt put it in parenthesis and stick a dollar sign in front of it, only good can come from this.
If somebody passes the list and map to you as constructor arguments, then you're not safe unless you make a copy on the way in, too, since the caller may retain a reference to those collections.
As far as copying return values: that's one way. Another way is to use the Collections.unmodifiableMap() and unmodifiableList() methods, which return a read-only view of a collection you're holding (presumably cheaper to create then copying the whole collection.) Yet another way would be not to return whole collections in the first place; i.e., provide a "String getFromMap(String)" method, if necessary.
The only thing about the final solution is that the caller has to know not to try to call put on the map returned. This may not appear until 6 months time when someone else is modifying the calling code and gets an UnsupportedOperationException. If you only exposed an interface containing, say, getFromMap as Ernest said then its clear you cant edit it. Personal taste I suppose... [ November 30, 2008: Message edited by: Tom Johnson ]
In my scenario handing over a complete 'master copy' of the map/array to the client is important. So a method to extract individual values is not that useful.
But you raise a good point, as the client does need to be able to edit the map/array, so I will edit the class to return a fresh modifiable copy of the hashmap/array, this will avoid problems as you suggest.
It's really just a decorator class that prevents the altering of the internal Map reference(s), but it still allows access to the original objects, which means that someone (either the holder of the "unmodifiable map", or the holder of the original map) could get an object, and alter its contents.
What Lyle says is true in the general case, but in the specific case presented here where the collections are of an immutable type, then there is no need for deep copies. It goes to accent Joshua Bloch's stress on immutable objects when possible - if you use immutable objects inside the collection then you don't have to spend the time or worry about making copies.
Joined: Dec 19, 2010
Steve Luke wrote:What Lyle says is true in the general case, but in the specific case presented here where the collections are of an immutable type, then there is no need for deep copies. It goes to accent Joshua Bloch's stress on immutable objects when possible - if you use immutable objects inside the collection then you don't have to spend the time or worry about making copies.