Avoid Enumeration For Loop Control
ID |
java.loop_legacy_enumeration |
Severity |
info |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Best Practice |
Language |
Java |
Tags |
efficiency |
Description
Reports the use of java.util.Enumeration as the driver of a while or do-while loop — the classic while (e.hasMoreElements()) { e.nextElement(); } pattern.
Rationale
Enumeration predates the Collections framework and has been superseded in practical code by Iterator and Iterable:
-
it is not
Iterable, so it cannot be used with the enhancedfor-eachloop; -
it does not support element removal (
Iterator.remove()); -
method names (
hasMoreElements,nextElement) are verbose compared with the idiomatichasNext/next.
In practice the Enumeration almost always comes out of an API whose signature the caller cannot change — ServletContext.getInitParameterNames(), HttpServletRequest.getHeaderNames(), ResourceBundle.getKeys(), ZipFile.entries(). Changing the type is therefore not the remediation; wrapping the enumeration in a List at the call site is, and it works for every one of those APIs.
// Bad — legacy Enumeration drives the loop
Enumeration<String> e = vector.elements();
while (e.hasMoreElements()) {
process(e.nextElement());
}
// Good — enhanced for-each over the collection
for (String s : vector) {
process(s);
}
// Good — Iterator when removal is needed
Iterator<String> it = vector.iterator();
while (it.hasNext()) {
if (isStale(it.next())) {
it.remove();
}
}
Remediation
Wrap the enumeration with Collections.list(…) and iterate the resulting List with for-each — this works whoever owns the API:
for (String name : Collections.list(request.getHeaderNames())) {
process(name);
}
When the receiver is a collection you control, take an Iterator from it instead (Collection.iterator()), or iterate it directly with for-each.
The receiver must resolve to java.util.Enumeration for the rule to fire; a hasMoreElements() on an unresolved or unrelated type is not reported.