java 9 引入 list.of() 和 set.of() 等静态工厂方法,用于创建内存高效、构造时校验 null 和重复元素、最多支持10个参数的不可变集合,适用于常量定义、临时参数和测试预期结果等场景。

Java 9 引入了 List.of() 和 Set.of() 这类静态工厂方法,用于创建**不可变(immutable)集合**。它们不是新增的集合类型,而是便捷、高效、安全地构造小型只读集合的工具。
为什么需要 List.of() 和 Set.of()?
在 Java 9 之前,创建不可变集合需借助 Collections.unmodifiableList() 或 Arrays.asList() + 包装,但这些方式要么可被底层修改影响(如数组引用泄漏),要么代码冗长、运行时才校验。而 List.of() 和 Set.of():
- 直接返回高度优化的专用不可变实现(如
ImmutableCollections.ListN),内存占用小、访问快 - 在构造时就拒绝 null 元素(
Set.of()还要求元素互异),避免运行时意外 NPE 或逻辑错误 - 语法简洁,语义明确:“我要一个确定内容、绝不会变的集合”
核心行为与限制
这些工厂方法的行为有严格约定,使用前必须清楚:
-
不可修改性是深层的:不仅不支持
add()、remove()等操作(调用即抛UnsupportedOperationException),连反射或序列化绕过都受内部机制防护 -
空值处理一致且严格:任一参数为
null,立即抛NullPointerException;Set.of()中重复元素会触发IllegalArgumentException -
容量有限制:最多支持 10 个显式参数(如
List.of(a,b,c,...,j))。超过需用List.ofArray(array)形式(实际是Arrays.asList().toArray()后包装,注意数组本身仍可变) -
不保证线程安全的“发布安全”:虽然集合不可变,但若构造时传入的对象本身可变(如一个可修改的
StringBuilder),外部仍可通过该对象改变状态 —— 不可变的是集合容器,不是其元素
与旧方式对比:何时该用?
适用场景很明确:
- 定义常量集合,如配置项白名单:
private static final Set<string> SUPPORTED_TYPES = Set.of("json", "xml", "yaml");</string> - 作为方法临时参数,避免无意修改:
processItems(List.of("task1", "task2")); - 单元测试中构造预期结果,语义清晰、无需额外断言是否被改
不适合场景:
- 需要动态增删的集合 —— 它们天生不可变,别强行包装可变集合
- 含大量元素(百级以上)—— 内部实现针对小集合优化,大数据量建议用
new ArrayList(...)+Collections.unmodifiableList()或 Guava 的ImmutableList - 需保持插入顺序但允许重复的不可变序列 ——
List.of()可以,但若需更复杂行为(如自定义比较器的不可变 set),仍需其他方案
一点提醒:Map.of() 也同理
Java 9 同时提供了 Map.of() 和 Map.ofEntries(),规则类似:键值对数上限、null 拒绝、重复 key 报错、不可变。它们和 List/Map 工厂共同构成一套轻量级不可变数据构造工具链,风格统一,学习成本低。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










