...
This noncompliant code example attempts to process a collection of objects integers using an enhanced for loop. It further intends to skip processing modify one item in the collection .for processing:
Code Block | |||||
---|---|---|---|---|---|
| |||||
List<Integer> list = Arrays.asList(new Integer[] {13, 14, 15}); boolean first = true; System.out.println("Processing list...");Collection<ProcessObj> processThese = // ... for (ProcessObjInteger processMei: processTheselist) { if (someConditionfirst) { // found the itemfirst to= skipfalse; someConditioni = false new Integer(99); } System.out.println(" New item: processMe" = processMe.getNext(+ i); // attempt to skip to next item } processMe.doTheProcessing(); // process the object } |
The attempt to skip to the next item appears to succeed because the assignment is successful and the value of processMe
is updated. Unlike a basic for
loop, however, the assignment leaves the overall iteration order of the loop unchanged. Consequently, the object following the skipped object is processed twice.
...
process i
}
System.out.println("Modified list?");
for (Integer i: list) {
System.out.println("List item: " + i);
}
|
However, this does not actually modify the list, as shown by the program's output:
Processing list...
New item: 99
New item: 14
New item: 15
Modified list?
List item: 13
List item: 14
List item: 15
Noncompliant Code Example
Declaring i
to be final mitigates this code example, by causing the compiler to fail to permit i
to be assigned a new value.
Code Block | ||||
---|---|---|---|---|
| ||||
...
for (final Integer i: list) {
...
|
Compliant Solution
This compliant solution correctly processes each object in the collection no more than onceprocesses the 'modified' list, but leaves the actual list unchanged.
Code Block | ||||
---|---|---|---|---|
| ||||
Collection<ProcessObj> processThese = // ... for (final ProcessObjInteger processMei: processTheselist) { ifInteger (someCondition)item { // found the item to skip= i; if (first) { someConditionfirst = false; continue;item //= skip by continuing to next iterationnew Integer(99); } processMeSystem.out.doTheProcessing(println(" New item: " + item); // process the objectitem } |
Risk Assessment
Assignments to the loop variable of an enhanced for
loop (for-each idiom) fail to affect the overall iteration order, lead to programmer confusion, and can leave data in a fragile or inconsistent state.
...