商城首页欢迎来到中国正版软件门户

您的位置: 首页 > 文章列表 > 编程开发 > 如何在 Java 中利用 EnumSet.allOf() 快速获取枚举类中定义的全部常量集合

如何在 Java 中利用 EnumSet.allOf() 快速获取枚举类中定义的全部常量集合

  发布于2026-07-09 阅读(0)

扫一扫,手机访问

先说说 EnumSet.allOf() 这个 API 最核心的几个特点——它只认具体的枚举类,你必须老老实实传一个 Class 对象过去(比如 Color.class)。底层依赖枚举类的 values() 方法,所以没法拿匿名子类或者反射动态生成的东西来糊弄它,否则直接抛 IllegalArgumentException。返回的集合支持 clear() 操作(清空后就变成空集,不再是全量),但你不能 add()remove()。性能上比 Arrays.asList() 的方案快出一截,尤其在频繁做集合运算的场景下表现明显。

如何在 Ja va 中利用 EnumSet.allOf() 快速获取枚举类中定义的全部常量集合

EnumSet.allOf() 的适用前提和类型约束

这玩意儿只能在枚举类型上用,而且必须传给它该枚举的 Class 对象。它背地里依赖枚举类的 values() 方法,所以你不能拿匿名子类或者反射造出来的东西糊弄它,否则等着 IllegalArgumentException 招呼你。

  • 第一,你必须老老实实传一个具体的枚举类 Class,比如 Color.class,别想着传个 Object.class 或者父类过去,编译都过不去。
  • 第二,枚举类内部不能有出问题的初始化逻辑,比如在 static 块里抛异常,那 allOf() 调用时可能会炸个 ExceptionInInitializerError
  • 第三,返回的集合有点特别——你不能往里加新元素,也不能删现有元素,但可以 clear() 一下全部清空(清完后当然就不是“全量”了)。

为什么不用 values() 直接转 List 而要用 EnumSet.allOf()?

好问题。EnumSet 是 Ja va 专门为枚举量身定做的高性能集合,底层用的是位向量——long 或者 long[],空间占用小得惊人,遍历和判断是否包含元素(contains)都是 O(1) 的复杂度。相比之下,Arrays.asList(Color.values()) 返回的是一个固定大小的 ArrayList,既不能增删元素,又没有位运算加持,性能上差了一截。

  • EnumSet.allOf(Color.class) 创建的是一个可以修改的集合,比如你可以在上面调用 retainAll()removeAll() 做集合运算。而 Arrays.asList(...) 返回的列表,你要是敢调 remove(),它会直接抛 UnsupportedOperationException
  • 后续如果要频繁做求差集、并集之类的操作,EnumSetHashSetArrayList 快了不止一个数量级。
  • 但有一点要注意:它不是线程安全的,多线程环境里需要自己加锁同步。

常见误用与运行时错误

最常踩的坑就是泛型擦除——编译能过,运行却翻车:

  • 错误写法:EnumSet.allOf((Class) MyEnum.class) —— 强制转型绕过了编译检查,一旦传错类,运行时就等着 ClassCastException 或者 IllegalArgumentException 吧。
  • 错误写法:EnumSet.allOf(SomeInterface.class) —— 就算枚举实现了这个接口,你也得传枚举自身的 Class,接口类不行。
  • 错误写法:EnumSet.allOf(null) —— 传空?直接 NullPointerException
  • 还有个冷知识:如果枚举常量超过 64 个,EnumSet 会自动切换成 RegularEnumSet(基于 long[]),行为上保持一致,但某些老版本的 Android 对大枚举的位操作可能会有兼容性毛病。

一个安全封装的工具方法示例

要是你经常需要获取全量枚举集合,又不想每次都手写 .class,可以弄个工具方法,顺便用泛型把类型约束死:

public static > EnumSet allOf(Class enumClass) {    return EnumSet.allOf(enumClass);}

调用的时候这么写:EnumSet all = Utils.allOf(Status.class); 编译器看到这个签名就会强制 E 必须是枚举类型,如果你传个非枚举类进来,编译直接报错,比裸调 EnumSet.allOf() 安全得多。

最后得提醒一句:EnumSet 的“全量”语义只在创建那一刻成立。如果后续你在代码里新增了枚举常量,但没重新编译调用方,那 allOf() 返回的仍然是旧版本的全部常量——这个细节在热更新或者模块化部署的场景下特别容易被忽略。

本文转载于:https://www.php.cn/faq/2411152.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。

热门关注