Java 可变对象包装在不可变对象中是否安全?

Java 可变对象包装在不可变对象中是否安全?,java,immutability,Java,Immutability,如果我有一个如下所示的数据结构: ImmutableObj<MutableMap<String,Integer>> myObj; public Map<String, Integer> wordFruquencyIn(String book, String word) { //do calculation here Map<String, Integer> result = //result return Collect

如果我有一个如下所示的数据结构:

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

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

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

当您不像这样公开指向原始可变对象的链接时是安全的(列表示例,集合类中提供了相同的映射方法):

List strings=Arrays.asList(“Foo”、“Bar”);
List ImmutableString=Collections.unmodifiableList(字符串);
因为您可能必须通过字符串列表修改ImmutableString列表。 更好的方法是根本没有指向可变列表的链接,如:

List<String> immutableStrings = Collections.unmodifiableList(Arrays.asList("Foo", "Bar"));
List immutableStrings=Collections.unmodifiableList(Arrays.asList(“Foo”,“Bar”));
在这里,我们没有使用foo和bar链接到内部可变列表,并且不能修改ImmutableString列表

这是一个综合的例子,从你的问题下面的对话中我了解到你可能想要这样的东西:

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

    Map<String, Integer> result = //result
    return Collections.unmodifiableMap(result); // return unmodifiable map 
}
公共映射词fruquencyin(字符串书,字符串词){
//在这里做计算
映射结果=//结果
返回集合。不可修改映射(结果);//返回不可修改映射
}
最好创建表示计算结果的自定义类,而不是映射,因为映射、列表等的契约。。。不清楚的是,您不知道它们是可变的还是不可变的(缺少方法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() {}

}
public Statistics wordFruquencyIn(字符串本,字符串字){
//在这里做计算
映射结果=//结果
返回新的统计数据impl(结果);
}
公共接口统计{
公共字符串字(){}
公共整数时间(){}
}

您可以创建符合此接口约定的统计接口的任何实现,并在其内部具有映射或任何可变数据,与此类通信的唯一方法是询问返回已不可变字符串的
word()
,或返回原语的
times()

安全原因是什么?可变映射中的值可能会更改;你的设计是否依赖于不发生这种情况?不,这当然不足以使整个事情不变。对象内部的映射也必须是不可变的。事实上,我甚至可以说它没有包装在不可变的对象中。“外部”对象是可变的,因为它的状态(包括“内部”对象)可以改变。@ElliottFrisch这是一个很好的问题。假设我想保留一本字典,记录一个单词在一本书中出现的次数(存储在MutableMap中)。我说这个实现会导致问题,对吗?@Jesper谢谢你的评论。在这种情况下,这种结构有用吗?