包含在不可变对象内的可变对象是否安全?

时间:2017-11-26 16:06:49

标签: java immutability

如果我的数据结构如下:

ImmutableObj<MutableMap<String,Integer>> myObj;

以上是否足以确保免疫力?或者我是否必须使MutableMap不可变?

1 个答案:

答案 0 :(得分:1)

当你不公开像这样的原始可变对象的链接时是安全的(带有列表的例子,地图的相同方法出现在Collections类中):

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

因为您可能必须通过字符串列表修改immutableStrings列表。 更好的方法是根本没有可变列表的链接:

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

这里我们没有使用foo和bar链接到内部可变列表,也无法修改immutableStrings列表。

这是合成的例子,根据你提问的对话,我明白你可能想要这样的东西:

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

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

最好创建代表计算结果而不是地图的自定义类,因为Map,List等的合同......不清楚你不知道它们是否可变(缺少方法isMutable()和缺乏一般早期Java版本中的设计(参见本例中的LSP原理))。重构后你的代码可能是这样的:

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() {}

}

您可以创建任何实现Statistics接口的实现,该接口实现此接口的合约并且具有内部映射或任何可变数据,只有一种与此类通信的方式是询问返回已经不可变字符串的word()或{{ 1}}返回一个原语。