xcoder
xcoder

Reputation: 1436

Is mutable object wrapped inside an immutable object safe?

If I have a data structure which looks like this:

ImmutableObj<MutableMap<String,Integer>> myObj;

Is the above enough to ensure immunity? Or do I have to make MutableMap immutable as well?

Upvotes: 1

Views: 78

Answers (1)

fxrbfg
fxrbfg

Reputation: 1786

It's safe when you don't expose link to original mutable object like this (example with lists, same method for map is presents in Collections class):

List<String> strings = Arrays.asList("Foo", "Bar"); 
List<String> immutableStrings = Collections.unmodifiableList(strings);

because you may have to modify immutableStrings list through strings list. Better approach is to don't have links to mutable list at all like:

List<String> immutableStrings = Collections.unmodifiableList(Arrays.asList("Foo", "Bar"));

Here we don't have link to inner mutable list with foo and bar, and not able to modify immutableStrings list.

It's synthetic example, from conversation under your question i understand that you may want something like this:

public Map<String, Integer> wordFruquencyIn(String book, String word) {
    //do calculation here

    Map<String, Integer> result = //result
    return Collections.unmodifiableMap(result); // return unmodifiable map 
}

Better to create custom class that represents result of calculation instead of map, because contracts of Map, List, etc... unclear in way you don't know if they mutable or not (lack of method isMutable() and lack of design in early java versions in general (see LSP principle in this case)). After refactor you code may be like that:

public Statistics wordFruquencyIn(String book, String word) {
    //do calculation here

    Map<String, Integer> result = //result
    return new StatisticsImpl(result);
}

public interface Statistics {  

    public String word() {} 

    public int times() {}

}

You may create any implementation of Statistics interface that fulfill contract of this interface and have map inside or any mutable data, only one way to communicate with this class is ask about word() that returns already immutable string or times() that returns a primitive.

Upvotes: 1

Related Questions