Collections.unmodifiableList 返回只读视图,拦截add/remove/set/clear等修改操作并抛出UnsupportedOperationException,但不阻止原始列表被其他引用修改,仅提供运行时防护。

用 Collections.unmodifiableList 包一层,不是真的“锁住”了原列表,而是返回一个无法执行修改操作的视图。关键点在于:它保护的是“访问入口”,不保护底层数据本身。
只读视图的本质是拦截修改操作
调用 unmodifiableList 后得到的 List 实例,所有会改变结构或元素的方法(如 add、remove、set、clear)都会直接抛出 UnsupportedOperationException。它内部持有一个对原始列表的引用,但所有写操作都被明确拒绝。
- 适合用于对外暴露集合字段,防止调用方意外或恶意修改
- 不增加额外存储开销,只是包装了一层代理
- 如果原始列表被其他地方悄悄改了,只读视图看到的内容也会变——它不隔离变化,只限制主动修改
必须确保原始引用不泄露
如果类中保存了一个可变列表,并通过 unmodifiableList 返回,但同时又提供了获取原始列表的方法(比如 getter 返回私有字段本身),那保护就形同虚设。
- 避免在类中保留对原始可变列表的 public 或 protected 访问途径
- 构造只读视图时,最好在初始化阶段完成,而不是每次 get 都重新包装(除非原始列表可能更新)
- 若需彻底隔离,应配合不可变对象(如使用
List.copyOf或ImmutableList)
注意与真正不可变集合的区别
Collections.unmodifiableXxx 系列是“运行时防护”,属于轻量级防御;而像 List.of()、ImmutableList(Guava)或 java.util.ImmutableCollections(Java 10+ 内部实现)才是编译期+运行期双重保障的不可变集合。
-
unmodifiableList允许原始列表被修改,只读视图只是“看不惯你改,但拦不住别人改” -
List.copyOf(list)(Java 10+)会创建新副本,切断与原列表的联系,更安全 - 若业务逻辑要求“内容绝对不变”,优先考虑不可变副本,而非只读视图
用对场景,它就是一道简洁有效的防线;用错地方,就只是自我安慰。

















