Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: overhauled code samples

...

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
bgColor#ffcccc#FFCCCC
langjava
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
bgColor#ffcccc
langjava
...
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
bgColor#ccccff
langjava
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.

...