在for循环声明中初始化变量的范围实际上不仅仅是块范围吗?

时间:2016-06-18 03:06:37

标签: java c# for-loop scope language-agnostic

考虑带有计数器的for循环:

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

一切都很好。 We say that i has "block" scope.

但是,为什么在for无法访问i++循环内声明的变量?

例如,为什么j不在此范围内,当它还有&#34;阻止&#34;范围并在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范围的问题,但没有关于j循环括号内for范围的问题。这是否意味着在技术上还有另一个范围,没有人谈论哪个是&#34; for-loop声明范围&#34;?如果是这样,我对如何在Java或C#等规范中定义此范围以及程序员通常所称的范围感兴趣。

编辑:是的,我知道我可以将循环声明为for (int j, i = 0; i < 100; i += j),但这仍然表明for循环声明的范围大于它们的大括号。

4 个答案:

答案 0 :(得分:3)

JLS 6.3指明范围界定的面部原因:

  

在基本的ForInit部分中声明的局部变量的范围   for statement(§14.14.1)包括以下所有内容:

     
      
  • 自己的初始化程序
  •   
  • for语句的ForInit部分右侧的任何其他声明符
  •   
  • for语句的表达式和ForUpdate部分
  •   
  • 包含的声明
  •   

“包含声明”for正文。 for正文中定义的变量没有特殊的范围规则。正常规则适用。 (它们也在JLS 6.3中。)

这种语言设计背后的原因包括(我猜 1 )以下内容:

  • 如果您不得不在循环体内查找变量声明那里 2 ,那么可读性就不好了。
  • 确定循环中声明的变量是否已明确初始化的逻辑很难指定,并且程序员很难理解。例如:

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

1 - 真正的原因只能在20世纪70年代为C的设计者所知。我怀疑Java设计者是否认为它与C不同。他们试图使Java“类似C”。

2 - 循环体中的某些东西可以修改循环变量。 :-(

答案 1 :(得分:0)

第一个Scope以void main {}开头,而不是像你的for循环范围之后的其他内部块一样,并且使用第一个块声明的所有变量对于范围的所有内部块都是可见的,而我们必须先声明变量使用它(在你的情况下是变量j)你在for循环中使用了变量而没有声明它,因此在声明之前不可能使用它,并且我们的光标由于从上到下的逐行逼近而到达for循环所有检查变量是否已声明?

答案 2 :(得分:0)

一个非常有趣的问题。如果从运行时透视图中看到j,则可以看到j应该是可见的非常好的一点,因为迭代后调用了增量表达式。

但是从编译器的角度来看,当它读取for循环语句,即(int i = 0; i < 100; i += j)时,它会期望j已经被声明。

我猜你可以说我有一个额外的声明范围,与i和j都有的块范围相比。

答案 3 :(得分:-1)

变量J在声明/初始化之前被引用。当第一次循环执行时,JVM将没有对它的引用。

您已在循环内初始化变量j。

我希望这能解决你的问题。