It's actually reasonably simple.
Basically, it's saying to not...
1- Make available any reference to any mutable object that your object might contain.
So if your Class
contained a java.util.List
as one of it's fields, there should be no way for any client using your Class
to gain a reference directly to the List
field, either via public
deceleration or getter of some kind.
For example...
public class BadImmutableExample {
public List<String> myStrings; // This can not be referenced by the client
/*...*/
}
Would be bad, because the field myStrings
is accessible to any body to make modifications to...
In the case you had to return the values in the List
you would either be required to return a copy of the List
(not a reference to it) or return an array of the values, for example.
For example...
public class BadImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
/*...*/
public List<String> getMyStrings() {
return myStrings;
}
}
Would expose the List
myStrings
to any clients, which would allow them to modify it.
In this case, you could also use Collections.unmodifiableList(myStrings)
to make the list unmodifiable, or return new ArrayList<String>(myStrings)
or return an array of String
instead...
2- Never initialise such a field to a client provided object...
Basically this means that if your Class
requires the client to seed it with some kind of value or values, you should never maintain a reference directly them, instead, again, make a copy for you own reference...
For example...
public class BadImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
public ImmutableExample(List<String> clientStrings) {
myStrings = clientStrings;
}
}
Would break this rule, as any changes to clientStrings
would be immediately reflected within you class.
Instead, you could do something like...
public class BetterImmutableExample {
private List<String> myStrings; // This can not be referenced by the client
public ImmutableExample(List<String> clientStrings) {
myStrings = new ArrayList<String>(clientStrings);
}
}
Instead, which will make a copy of the client supplied list, but which will no longer reflect changes made to it (the client supplied list)