Question

To make a immutable class , Effective Java has one last condition.

To make a class immutable, follow these five rules:

5- Ensure exclusive access to any mutable components. If your class has any fields that refer to mutable objects, ensure that clients of the class cannot obtain references to these objects. Never initialize such a field to a client-provided object reference nor return the object reference from an accessor. Make defensive copies (Item 24) in contructors, accessors, and readObject methods

public final class ImmutableClass {


    private MutableObject mutableObject;

    // If I should not provide getter for this object. Then what is the use of this variable after I have
    //initalised in the constructor
}

Can somebody explain me this point?

Was it helpful?

Solution

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)

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