为什么枚举不可迭代?

时间:2020-03-05 18:43:06  来源:igfitidea点击:

在Java 5及更高版本中,我们具有foreach循环,该循环可神奇地实现实现Iterable的任何事物:

for (Object o : list) {
  doStuff(o);
}

但是,Enumerable仍然没有实现Iterable,这意味着要对Enumeration进行迭代,我们必须执行以下操作:

for(; e.hasMoreElements() ;) {
  doStuff(e.nextElement());
}

有谁知道Enumeration仍然不实现Iterable的原因吗?

编辑:为澄清起见,我不是在谈论枚举的语言概念,而是在Java API中称为"枚举"的Java特定类。

解决方案

回答

枚举没有被修改为支持Iterable,因为它是一个接口,而不是一个具体的类(例如Vector,它被修改为支持Collections接口)。

如果将Enumeration更改为支持Iterable,则会破坏很多人的代码。

回答

AFAIK枚举有点"不建议使用":

Iterator takes the place of
  Enumeration in the Java collections
  framework

我希望他们使用JSR 315将Servlet API更改为使用Iterator而不是Enumeration。

回答

"枚举"实现"可迭代"是没有意义的。 "可迭代"是"迭代器"的工厂方法。 "枚举"类似于"迭代器",并且仅维护单个枚举的状态。

因此,请小心尝试将"枚举"包装为"可迭代"。如果有人给我传递了一个"可迭代的",我将假定可以重复调用" iterator()",并根据需要创建任意数量的" Iterator"实例,并在每个实例上进行独立迭代。包装好的"枚举"将无法履行此合同;不要让我们包装的"枚举"从我们自己的代码中转义。 (顺便说一句,我注意到Java 7的DirectoryStream违反了这种期望,也不应该允许它"转义"。)

"枚举"就像是"迭代器",而不是"可迭代"。 "集合"是"可迭代的"。 Iterator不是。

我们不能这样做:

Vector<X> list = …
Iterator<X> i = list.iterator();
for (X x : i) {
    x.doStuff();
}

因此,这样做是没有意义的:

Vector<X> list = …
Enumeration<X> i = list.enumeration();
for (X x : i) {
    x.doStuff();
}

没有等效于"可迭代"的"可枚举"。可以添加它而无需中断for循环中的任何工作,但是这样做有什么意义呢?如果我们能够实现这个新的" Enumerable"接口,为什么不仅仅实现" Iterable"呢?

回答

作为将枚举与增强的for循环结合使用的简便方法,请使用java.util.Collections.list转换为ArrayList。

for (TableColumn col : Collections.list(columnModel.getColumns()) {

(javax.swing.table.TableColumnModel.getColumns返回枚举。)

请注意,这可能会稍微降低效率。