Question

I have a query regarding creating a Immutable class. Following are the points which I take in consideration:

  1. Make the class final
  2. Make all members final, set them explicitly, in a static block, or in the constructor
  3. Make all members private
  4. No Methods that modify state
  5. Be extremely careful to limit access to mutable member components(remember the field may be final but the object can still be mutable. ie private final Date imStillMutable) - See defensive copying or its cousin copy constructors for more info.


But I did not understand the 5 point completely at all, could you please advise or show me a example in which the 5 point is clear in that example?

Was it helpful?

Solution

Point 5 suggests that any time you have any methods which would return something to do with a mutable object, you'd want to create a copy which is independent of the private state. For example:

public final class Foo
{
    private final List<String> strings;

    public Foo(List<String> strings)
    {
        // Defensive copy on construction. Protects from constructing
        // code mutating the list.
        this.strings = new ArrayList<String>(strings);
    }

    public List<String> getStrings()
    {
        // Defensive copy on read. Protects from clients mutating the list.
        return new ArrayList<String>(strings);
    }
}

Note that the defensive copying is only required when the state is mutable. For example, if you used an ImmutableList (e.g. from Guava) as the state in the above class, you'd need to create a new list on construction (unless the input is also an ImmutableList) but not in getStrings.

Also note that in this case String is immutable, so we don't need to copy each string. If this were a List<StringBuilder> we'd need to create a new list and a new copy of each element as part of the defensive copy. As you can see, life becomes simpler when all your state is immutable too.

OTHER TIPS

final means that the pointer can't point to another reference. For example:

final Object obj = new Object();
obj = new Object(); //Invalid

But final doesn't prevent modifiying the object:

obj.setWhatever("aaa"); //Perfectly valid

If you haven't limited the access to the members, then anyone can get the object and modify it.

For example: yourClass.getObject().setWhatever("aaa").

Defensive copying means that getObject() won't return directly the object, but it will make a copy of it and then return it. This way if the caller modifies the returned object, it won't modify the original member of the class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top