I am reading \"Effective Java\" by Joshua Bloch, item 39 make defensive copy, and I have some questions. I always use the following construct:
MyObject.getSo
Documentation is the way you (should) know. MyObject
should document whether the things it exposes can or should be used to modify MyObject
itself. You should only ever modify an object in the ways explicitly granted by the class.
For example, here are the Javadocs for two methods in List
, one whose result can't be used to change the List
, and one whose result can change the List
:
toArray()
:
The returned array will be "safe" in that no references to it are maintained by this list. (In other words, this method must allocate a new array even if this list is backed by an array). The caller is thus free to modify the returned array.
subList()
:
The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. The returned list supports all of the optional list operations supported by this list.
I would say that silence from the documentation means that you shouldn't use it to mutate the object (use it only for read-only purposes).
call getSomeRef() two times and compare there reference if they are different then function is returning the copy else it is returning the same instance.
if(MyObject.getSomeRef() == MyObject.getSomeRef()){
// same instance
}else{
// copied instance
}
I would suggest defining a readableThing
interface or class, and deriving from it mutableThing
and immutableThing
interfaces. A property getter should return one of those interfaces based upon the returned item's relation to the list:
It's too bad Java doesn't inherently do a better job of indicating declaratively who "owns" various objects. Before the days of GC frameworks, it was annoying having to keep track of who owned all objects, whether they were mutable or not. Since immutable objects often have no natural owner, tracking ownership of immutable objects was a major hassle. Generally, however, any object Foo
with state that can be mutated should have exactly one owner which regards mutable aspects of Foo
's state as being parts of its own state. For example, an ArrayList
is the owner of an array which holds the list items. One is unlikely to write bug-free programs using mutable objects if one doesn't keep track of who owns them (or at least their mutable aspects).
You're violating two rules of OO programming:
Note that these rules are just rules, and that they can, or even must be broken sometimes.
But if some data is owned by an object, and the object is supposed to guarantee some invariants on the objects it owns, then it should not expose its mutable internal data structures to the outside. Hence the need for a defensive copy.
Another often used idiom is to return unmodifiable views of the mutable data structures:
public List<Foo> getFoos() {
return Collections.unmodifiableList(this.foos);
}
This idiom, or the defensive copy idiom, can be important, for example, if you must make sure that every modification to the list goes through the object:
public void addFoo(Foo foo) {
this.foos.add(foo);
someListener.fooAsBeenAdded(foo);
}
If you don't make a defensive copy or return an unmodifiable view of the list, a caller could add a foo to the list directly, and the listener would not be called.
Defensive copy is a good idea, but you need to understand when and where it gets used. If the web of objects you are manipulating is internal, and it not intended to be thread safe, then the defensive copying is being mis-applied.
On the other hand, if this is web of objects that are getting exposed publicly, then you are at risk of violating Law of Demeter. If so, consider exposing a manipulator API on your myObject
.
As a sidenote, your code sample made the getSomeRef
look like a static API. I would suggest that you name any static API that returns a copy of some singleton accordingly (e.g. copyOfSomething()
). Similarly for a static factory method.