Collections.unmodifiableList 和防御副本

新手上路,请多包涵

如果我写

List<Integer> a1 = Arrays.asList(1, 2, 3);
List<Integer> a2 = Collections.unmodifiableList(a1);

a2 是只读的,但如果我写

a1.set(0,10);

然后 a2 也被修改。

如果在 API 中说:

返回指定集合的不可修改视图。此方法允许模块为用户提供对内部集合的“只读”访问权限。

那么,为什么如果我修改原始集合也会修改目标复制的集合?

也许我误解了它的意思,如果是的话,写一份该系列的防御性副本的方法是什么?

原文由 xdevel2000 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 620
2 个回答

是的,你没看错。这个想法是 umodifiableCollection 返回的对象不能直接更改,但可以通过其他方式更改(通过直接更改内部集合有效)。

只要有东西可以访问内部列表,就可以更改“不可修改”的集合。

这就是为什么你 通常 构建一个不可修改的集合并确保没有任何东西可以到达内部列表:

 Collection<Integer> myUmodifiableCollection = Collection.umodifiableCollection(Arrays.asList(1, 2, 3));

由于没有任何东西获得对 List 创建的 asList 的引用,这是一个真正不可修改的集合。

这种做法的好处是你根本不需要复制原来的集合/列表,避免了内存和计算能力的使用。

Guava 提供 ImmutableCollection 类(及其子类,例如 ImmutableList ),它提供真正的不可变集合(通常通过复制源代码)。

原文由 Joachim Sauer 发布,翻译遵循 CC BY-SA 3.0 许可协议

也许我误解了它的意思,如果是的话,写一份该系列的防御性副本的方法是什么?

通常,您会这样使用它:

 private List<Integer> a1 = Arrays.asList(1, 2, 3);

public List<Integer> getUnmodifiable() {
    return Collections.unmodifiableList(a1);
}

调用 getUnmodifiable 并且 无法访问您的类内部的人(即他们无法访问私有变量 a1 ),将无法修改返回的列表.

原文由 assylias 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题