不能改,任何修改操作都会抛出unsupportedoperationexception;其为私有静态内部类,add/remove/clear均直接抛异常,且set无set()方法,与singletonlist混淆会导致误判;二者均不可序列化、不支持null;反射修改在jdk9+被禁止,推荐用set.of()替代。

singleton返回的集合真不能改吗?
不能改,任何修改操作都会抛出UnsupportedOperationException。这不是“写保护”或“运行时检查”,而是从设计上就切断了所有变更入口——Collections.singleton()返回的是一个私有静态内部类实例,它的add()、remove()、clear()等方法全部直接抛异常。
为什么add()和set()行为看起来不一样?
因为singleton()返回的是Set,不是List,压根没有set(int, E)方法。有人误以为能调用set(),其实是把Collections.singletonList()搞混了——后者返回不可变List,同样不支持set(),调用会直接报错:java.lang.UnsupportedOperationException。
-
Collections.singleton("a")→ 返回Set,无set()方法,调用add()报错 -
Collections.singletonList("a")→ 返回List,有get()但无set(),强行转型后调用set()也报错 - 二者都不可序列化(除非元素本身可序列化),且都不支持
null(singleton(null)会抛NullPointerException)
想“假装可变”但又不想破坏契约?别试
有人试图用反射绕过限制,比如获取内部element字段再赋值。这不仅违反API契约,而且在JDK 9+模块系统下默认被禁止;更关键的是,这类集合常被用在并发或校验场景(如Spring配置、Guava预检),一旦被篡改,错误会在下游才暴露,排查成本极高。
- 反射修改
SingletonSet的element字段:JDK 12+会触发InaccessibleObjectException - 用
Arrays.asList()替代?不行,它返回的List支持set(),但不满足“单元素+不可变”语义 - 真需要可变单元素容器?自己封装一个带状态检查的
MutableSingleton,别硬套Collections工具类
兼容性与性能要注意什么?
这个集合对象极轻量:不扩容、不哈希、不复制,内存占用就是对象头 + 一个引用字段。但要注意两点:
立即学习“Java免费学习笔记(深入)”;
- JDK 10 引入了
Set.of(),Set.of("a")语义等价但返回的是不同实现类,行为一致,推荐新代码优先用Set.of() - Android API Level Set.of(),若需兼容旧版本,仍得用
Collections.singleton(),但要确认目标SDK没禁用反射(某些加固方案会拦截) - 所有不可变集合(包括
singleton)的hashCode()和equals()都严格基于元素值,这点和普通HashSet一致,不必额外处理
真正容易被忽略的,是它对null的零容忍——连构造都不让,不是等到add()才报错。只要传了null,立刻NullPointerException,连栈轨迹都短得只剩一行。










