This is the standard pattern of the for-each loop.
When you write
for(Type variable: expression) {
// body
}
the expression will be evaluated exactly once at the beginning of the loop and the resulting collection or array reference is remembered throughout the loop. This also implies, that if expression is a variable and this variable is assigned within the loop body, it has no effect on the ongoing loop.
The relevant part of the specification says:
…
Otherwise, the Expression necessarily has an array type, T[].
Let L1 ... Lm be the (possibly empty) sequence of labels immediately preceding the enhanced for statement.
The enhanced for statement is equivalent to a basic for statement of the form:
T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
{VariableModifier} TargetType Identifier = #a[#i];
Statement
}
#a and #i are automatically generated identifiers that are distinct from any other identifiers (automatically generated or otherwise) that are in scope at the point where the enhanced for statement occurs.
TargetType is the declared type of the local variable in the header of the enhanced for statement.
If you compare the decompiled version
public static int hashCode(byte[] value) {
int h = 0;
byte[] var2 = value;
int var3 = value.length;
for(int var4 = 0; var4 < var3; ++var4) {
byte v = var2[var4];
h = 31 * h + (v & 255);
}
return h;
}
with the actual source code
public static int hashCode(byte[] value) {
int h = 0;
for (byte v : value) {
h = 31 * h + (v & 0xff);
}
return h;
}
you will recognize the translation. var2, var3, and var4 are all synthetic variables. Things to note:
- In principle, a compiler could analyze the scenario to recognize that
value is a local variable which is not assigned in the loop body, so no additional variable would be needed here. But the savings compared to following the standard translation strategy have not been considered worth implementing the additional logic.
- Likewise, it’s the compilers decision whether to remember the invariant array size in another local variable. As shown above, the specification does not mandate it.
You could say that it is a weakness of the decompiler not to recognize the for-each loop and translate it back, however, there’s generally an ambiguity when trying to map compiled code to source code constructs, as a lot of variants exist to produce the same code.