Collections.enumeration用于向下兼容老库(如javax.swing),将现代Collection转为Enumeration;参数须为非空Collection,返回弱一致性快照Enumeration,不支持remove且遍历时修改集合行为未定义。

为什么需要 Collections.enumeration?
因为有些老库(比如早期的 javax.swing、java.beans 或某些 JDK 1.1–1.4 时代的第三方框架)只认 Enumeration,而你手头只有 List、Set 这类现代集合。它不是为了“升级”,而是为了「向下兼容」——把新集合塞进老接口的模具里。
Collections.enumeration 怎么用?参数和返回值要注意什么
它只接受一个 Collection 参数,返回 Enumeration;不能传数组、不能传 Map(得先取 keySet() 或 values()),也不能传 null(会直接抛 NullPointerException)。
- 传入的
Collection如果后续被修改(比如在遍历中调用add()/remove()),Enumeration的行为是未定义的——多数实现会静默失败或抛ConcurrentModificationException - 返回的
Enumeration是**弱一致性快照**:它不反映原集合后续的变更,也不保证线程安全 - 不支持
remove()操作(Enumeration接口本身就没有这个方法)
示例:
List<String> list = Arrays.asList("a", "b", "c");
Enumeration<String> e = Collections.enumeration(list); // ✅ 正确
// Enumeration<String> bad = Collections.enumeration(null); // ❌ NPE
替代方案比 Collections.enumeration 更灵活的场景
当你要适配的 API 允许自定义 Enumeration 实现,或者需要控制遍历逻辑(比如过滤、延迟计算、流式生成),硬套 Collections.enumeration 反而受限。
立即学习“Java免费学习笔记(深入)”;
- 如果原集合很大,且你只需要前几项,用
Collections.enumeration会一次性持有所有引用——不如手写一个轻量Enumeration实现,按需nextElement() - 若要兼容
Iterator风格的异常语义(比如hasMoreElements()返回false后再调nextElement()应该抛NoSuchElementException),注意不同 JDK 版本对Collections.enumeration的异常处理略有差异(JDK 8+ 更严格) - Android 环境下,低版本(API Collections.enumeration 存在兼容性 bug,建议用
new Vector(collection).elements()替代(虽稍重,但稳定)
容易被忽略的线程安全陷阱
Collections.enumeration 本身不加锁,也不做同步包装。如果你把一个非线程安全的集合(如 ArrayList)传进去,又在另一个线程里并发修改它,Enumeration 遍历时大概率触发 ConcurrentModificationException,但这个异常可能出现在任意一次 nextElement() 调用中,而不是一开始就报错。
- 别指望用
Collections.synchronizedList包一层就万事大吉——它只同步单个方法,Enumeration的多次调用(hasMoreElements()+nextElement())之间仍有竞态窗口 - 真要跨线程安全传递,要么用
CopyOnWriteArrayList构造后传入,要么提前转成不可变集合(ImmutableList.copyOf(list)),再喂给Collections.enumeration
最常出问题的地方,是把刚 new 出来的 ArrayList 直接丢进去,然后一边往里 add,一边让老 API 在另一个上下文里遍历——这时候没报错只是运气好。










