EnumSet.copyOf()本质是重建而非克隆:它要求Collection元素同属一个枚举类型,校验后创建新EnumSet并逐个添加元素;支持copyOf(Collection)、copyOf(EnumSet)等重载,后者直接复制位向量更高效。

EnumSet.copyOf() 不能真正“克隆”任意 Collection,它只适用于元素类型与目标 EnumSet 枚举类型匹配的集合,且底层会重新构造一个新 EnumSet,而非浅拷贝或深拷贝意义上的克隆。
copyOf 方法的本质是重建,不是复制
EnumSet 是一个抽象类,所有实例都是其子类(如 RegularEnumSet 或 JumboEnumSet)的对象。它的 copyOf(Collection) 方法并不会复用原集合的内部结构,而是:
- 检查传入集合是否为空,若为空则返回空 EnumSet;
- 从集合中取出第一个元素,推断出枚举类型(要求所有元素必须属于同一枚举类);
- 创建一个新的 EnumSet 实例,然后逐个将元素添加进去(通过位运算高效设置);
- 原集合本身(比如 ArrayList、HashSet)不会被修改,也不会被持有引用。
只能用于同枚举类型的集合
传入的 Collection 中所有元素必须是同一个 enum 类型的实例,否则会抛出 ClassCastException 或 NullPointerException(如果含 null):
- ✅ 正确:EnumSet.copyOf(Arrays.asList(Color.RED, Color.BLUE))
- ❌ 错误:EnumSet.copyOf(Arrays.asList("a", "b")) —— 字符串不是枚举
- ❌ 错误:EnumSet.copyOf(Arrays.asList(Color.RED, Size.SMALL)) —— 混合不同枚举类型
常用调用方式与注意事项
有多个重载版本,最常用的是基于 Collection 的那个:
立即学习“Java免费学习笔记(深入)”;
-
EnumSet.copyOf(Collection<E> c):要求 c 非空且元素类型一致; -
EnumSet.copyOf(EnumSet<E> s):效率最高,直接复制位向量(内部 long[] 数组),等价于“真正意义上的快速复制”; -
EnumSet.copyOf(Iterable<E> iterable):Java 8+ 支持,本质还是遍历后重建。
注意:即使传入的是另一个 EnumSet,copyOf(Collection) 版本仍会走重建逻辑,不如直接用 copyOf(EnumSet) 高效。
替代方案:需要真正克隆时怎么办?
如果目标是“保留原集合结构 + 元素不变”,而不仅仅是获得一个相同内容的 EnumSet,那 EnumSet 本身不提供通用克隆能力。此时可考虑:
- 用
new ArrayList(original)克隆原始 List,再传给 EnumSet.copyOf; - 若原始集合是 EnumSet,优先使用
EnumSet.copyOf(existingEnumSet); - 不要依赖 EnumSet 做通用容器复制——它设计初衷就是高性能、有限类型、不可变语义的集合。


















