I have a rather simple question about variable scope.
I am familiar with the Enhanced For-Loops but I do not get why I should declare a new variable to keep each element. One example might clarify my question:
int[] ar = {1, 2, 3};
int i = 0;
for(i : ar) { // this causes an error if I do not declare a new variable: int i
// for(int i : ar) // this works fine
System.out.println(i);
}
So why I should declare this new variable? After all i
is accessible inside the for loop. I did not want to use any previous value of i
, just did not want to declare a new variable. (I guessed for other iterable items it might be faster using the same variable).
I guess that's how Enhanced For-Loops were built but does not this break the whole scope idea?
There is a question rising from the above behavior. Whether the compiler uses the same variable for the whole for
loop and just updates its value or it creates a new variable for each iteration?
An interesting part is that if I keep both declaration of int i (before and inside the for
loop) I even get a compiler error about
Duplicate local variable i
which makes (at least for me) things a bit more strange. So I cannot use the previous declared variable i
inside the for
loop but neither can I declare a new one inside it with the same name.
So why I should declare this new variable?
Because that's the way the syntax is defined.
After all i is accessible inside the for loop.
That's semantics. It's irrelevant to syntax.
I did not want to use any previous value of i, just did not want to declare a new variable. (I guessed for other iterable items it might be faster using the same variable).
Don 't guess about performance. Test and measure. But in this case there's nothing to measure, because any working code is faster than any non-working code.
Does this means that I have a local variable that gets different values or a different variable in each loop?
From a language point of view you have a different variable in each iteration. That’s why you can write:
for(final ItemType item: iterable) {
…
}
which makes a great difference as you can create inner class instances within the loop referring to the current element. With Java 8 you can use lambdas as well and even omit the final
modifier but the semantic does not change: you don’t get the surprising results like in C#.
I guessed for other iterable items it might be faster using the same variable
That’s nonsense. As long as you don’t have a clue of how the produced code looks like you shouldn’t even guess.
But if you are interested in the details of Java byte code: within a stack frame local variables are addressed by a number rather than by a name. And the local variables of your program are mapped to these storage locations by reusing the storage of local variables that went out of scope. It makes no difference whether the variable exists during the entire loop or is “recreated” on every iteration. It will still occupy just one slot within the stack frame. Hence, trying to “reuse local variables” on a source code level makes no sense at all. It just makes your program less readable.
Just to have the reference here: The JLS Section 14.14.2, The enhanced for statement defines the enhanced for-loop to have the following structure (relevant for this question):
EnhancedForStatement:
for ( {VariableModifier} UnannType VariableDeclaratorId : Expression ) Statement
where UnannType can be summarized to be "a type" (primitive, reference...). So giving the type of the loop variable is simply obligatory according to the language specification - causing the (admittedly: somewhat confusing) observations described in the question.
The int i
in the program is visible to the for loop and maybe other for loops beneath it (if present) under the same scope. But the i inside the for(int i : ar)
is local to the for loop. Hence ending once the execution of loop is over. Thats the syntax defined for foreach loop that "you have to use a variable with scope limited to the loop".
So why I should declare this new variable? After all i is accessible inside the for loop. I did not want to use any previous value of i, just did not want to declare a new variable. (I guessed for other iterable items it might be faster using the same variable).
Why would there be any considerable performance benefit if you use the same variable tiny primitive variable over and over versus creating a one only when needed and which gets destroyed after loop ends.
I don't think anyone has answered the original question beyond just declaring that that is the syntax. We all know that that is the syntax. The question is, logically speaking, why?
After all, you can use a variable defined just before a loop as the loop variable, as long as the loop is a non-enhanced for loop!