List.of()创建的列表不可修改,因其返回JVM内置不可变实现(如ImmutableCollections.List12),所有add、remove、set等修改方法均直接抛出UnsupportedOperationException,且不接受null元素。

为什么 List.of() 创建的列表不能修改
因为 List.of() 返回的是 JVM 内置的不可变实现(如 ImmutableCollections.List12),它在底层直接抛出 UnsupportedOperationException,而不是靠封装或防御性拷贝。调用 add()、remove()、set() 或任何修改方法都会立即失败。
常见错误现象:
- list.add("x") 报错:java.lang.UnsupportedOperationException
- list.clear() 同样报这个错
- 即使把返回值强制转成 ArrayList 也不行(类型转换失败,运行时报 ClassCastException)
List.of() 支持哪些参数形式和元素数量
它有多个重载版本,但核心就两条规则:
- 0 个参数 → 返回空的不可变列表:
List.of() - 1 到 10 个参数 → 直接接受对应数量的元素,例如:
List.of("a")、List.of(1, 2, 3) - 超过 10 个元素?必须用
List.ofArray()(不存在)—— 实际上得改用Arrays.asList(...).copyOf()(Java 10+)或Arrays.asList(...)+Collections.unmodifiableList()
注意:List.of(null) 是合法的,但 List.of("a", null, "b") 会直接抛 NullPointerException —— 它对 null 元素是零容忍的,哪怕只有一个。
和 Arrays.asList() 的关键区别在哪
两者看起来都能快速建表,但行为完全不同:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
-
Arrays.asList("a", "b")返回的是可变列表(底层是数组的包装类),能set(0, "x"),但不能add()(会抛UnsupportedOperationException,因为底层数组长度固定) -
List.of("a", "b")所有修改操作一律禁止,且不接受null -
Arrays.asList()返回的列表如果传入原始类型数组(如int[]),会把整个数组当一个元素(即变成List<int></int>);而List.of()对原始类型自动装箱,但不支持直接传原始类型数组
性能影响:两者都接近零拷贝,但 List.of() 在元素数 ≤10 时复用内部单例类,内存更省;Arrays.asList() 每次都新建对象。
什么时候该用 List.of(),什么时候不该用
适合场景:
- 配置项、枚举集合、测试用的固定数据集,比如:
private static final List<string> SUPPORTED_FORMATS = List.of("json", "xml", "yaml");</string> - 函数式编程中作为临时中间值,避免意外修改,如:
stream().filter(x -> List.of(1, 3, 5).contains(x)).toList()
不适合场景:
- 需要后续添加/删除元素的业务逻辑(改用
new ArrayList()) - 元素可能为
null(必须用Collections.unmodifiableList(Arrays.asList(...))或手动构建) - 元素数量动态不确定且可能超 10 个(考虑
List.copyOf(collection),Java 10+,它会做一次拷贝并返回不可变视图)
容易被忽略的一点:如果你在日志或调试中打印 List.of(1, 2, 3),看到的是 [1, 2, 3],和可变列表输出一样——光看输出无法判断是否真的不可变,得靠编译期约束和运行时异常来确认。

















