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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在for循环声明中初始化变量的范围实际上不仅仅是块范围吗?相关的知识,希望对你有一定的参考价值。

考虑一个带计数器的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不在此范围内,当它还具有“阻止”范围并且在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的范围。这是否意味着技术上还有另一个范围没有人谈论哪个是“for-loop声明范围”?如果是这样,我对如何在Java或C#等规范中定义此范围以及程序员通常所称的范围感兴趣。

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

答案

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

在for语句(第14.14.1节)的ForInit部分中声明的局部变量的范围包括以下所有内容:

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

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


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

  • 如果你不得不在循环体内查看声明为there2的变量,那么可读性就不好了。
  • 确定循环中声明的变量是否已明确初始化的逻辑很难指定,并且程序员很难理解。例: 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 - 循环体中的某些东西可以修改循环变量是很糟糕的。 :-(

另一答案

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

另一答案

一个非常有趣的问题。如果从运行时透视图中查看j,则会提出一个非常好的观点,即在迭代后调用increment表达式时j应该是可见的。

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

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

另一答案

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

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

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

以上是关于在for循环声明中初始化变量的范围实际上不仅仅是块范围吗?的主要内容,如果未能解决你的问题,请参考以下文章

js中let和var定义变量的区别

是否可以在for循环中声明两个不同类型的变量?

4/26打卡,范围for循环

For循环初始化

在基于范围的 for 循环中重新声明变量

c++、java、C#之间的for循环初始化变量范围