4castle 4castle - 5 months ago 11
Java Question

Is the scope of a variable initialized in a for loop declaration actually more than just block scope?

Consider a

for
loop with a counter:

for (int i = 0; i < 100; i++ /* `i` is visible here */) {
/* `i` is visible here */
}
/* `i` not visible here */


All is well. We say that
i
has "block" scope.


However, why is it that variables declared within the
for
loop are not accessible at
i++
?

For example, why is
j
not in scope here, when it also has "block" scope and was declared in a time period that is before
i += j
?

for (int i = 0; i < 100; i += j /* only `i` is visible here */) {
int j = 1;
/* `i` and `j` are visible here */
}
/* `i` and `j` are not visible here */


I have seen many questions concerning the scope of
i
, but not any concerning the scope of
j
within the
for
loop parentheses. Does this mean that there is technically another scope that nobody talks about which is "for-loop declaration scope"? If so, I'm interested in how this scope is defined in specs such as Java or C# and what scope it is generally referred to as by programmers.

Edit: Yes, I understand that I can declare the loop as
for (int j, i = 0; i < 100; i += j)
, but that still demonstrates that
for
loop declarations have a higher scope than their curly brackets.

Answer

The facial reason for this that JLS 6.3 specifies the scoping that way:

The scope of a local variable declared in the ForInit part of a basic for statement (ยง14.14.1) includes all of the following:

  • Its own initializer
  • Any further declarators to the right in the ForInit part of the for statement
  • The Expression and ForUpdate parts of the for statement
  • The contained Statement

The "contained statement" the for body. There are no special scoping rules for variables defined in a for body. The normal rules apply. (They are also in JLS 6.3.)


The reasons behind this language design include (I guess1) the following:

  • It would be bad for readability if you had to look inside the loop body for variables declared there2.
  • The logic to determine whether the variable declared in the loop was definitely initialized would be hard to specify, and difficult for programmers to understand. Example:

    for (i = 1; i < 10; i = i + j) {
        int j;
        if (i > 3) {
            j = 42;
        }
        // do stuff
    }
    

1 - The real reasons would only be known to the designers of C ... back in the 1970's. I seriously doubt that the Java designers even bothered to consider doing this kind of thing.

2 - It is bad enough that something in the loop body could modify a loop variable. :-(