在Java中重新声明循环内部的变量

在Java中,我们不能在具有相同名称的另一个变量的同一范围内声明变量:

int someInteger = 3; ... int someInteger = 13; 

语法错误,无法编译。 但是,如果我们把它放在一个循环中:

 for (int i = 0; i < 10; i++) { int someInteger = 3; } 

不产生错误,效果很好。 我们基本上声明了相同的变量。 是什么原因? 在这背后我不了解/理解的逻辑是什么?

想一想,在每次循环之后,范围被“破坏”,变量就消失了。 在下一个循环中,将创建一个新范围,并且可以在该范围内再次声明该变量。

出于类似的原因,你也可以这样做

  { int someInteger = 3; } { int someInteger = 13; } 

顺便说一下,Java不允许局部变量阴影,这可能不方便

  int x = 3; { int x = 13; // error! } Consumer consumer = (x)->print(x); // ERROR! // lambda parameter is treated like local variable Runnable r = ()->{ int x; ... } // ERROR // lambda body is treated like local block 

Java具有所谓的“块范围”,这意味着任何代码块(由封闭的花括号定义)声明一个变量,那个(并且只有那里)就是它存在的地方。 它还意味着每个变量只能在任何给定的块中声明一次。

当你说

 for (int i = 0; i < 10; i++) { int someInteger = 3; } 

每次迭代都会创建一个新块。 它类似于说

 { int someInteger = 3; } { int someInteger = 3; } ... 

在这种情况下,每个块中只有一个名为someInteger变量。

当你说

 { int someInteger = 3; ... int someInteger = 3; } 

编译器正确地抱怨您在相同的代码块(或范围)中声明了多个具有相同名称的变量。

在块的范围内,创建一个新的someInteger ,它会影响任何其他someInteger的词法范围。 关于可变阴影的维基百科条目(部分)

当在特定范围内声明的变量(决策块,方法或内部类)与在外部范围中声明的变量具有相同的名称时,会发生变量阴影 。 在标识符(名称而不是变量)级别,这称为名称屏蔽 。

每个变量都有一个范围。 范围嵌套在括号{} 。 当你离开这个范围时,这个上下文消失了,所以你可以定义其他具有相同名称的变量。 否则,你不能。

我会举两个例子:

 // define new scope named "methodA" public void methodA() { int a = 3; // define new scope named "loop" for (int i = 0; i < 10; i++) { int a = 6; // ERROR } } 

在上述情况下,您将遇到错误。 因为“loop”范围在“methodA”范围内,所以当你转到“循环”范围时,a的第一个定义仍然存在。

第二种情况:

 // define new scope named "methodA" public void methodA() { // define new scope inside methodA scope { int a = 3; } // define new scope named "loop" for (int i = 0; i < 10; i++) { int a = 6; // NO ERROR } } 

上面的代码会成功编译,因为第一个定义了a在不同范围内的第二个定义,而那些作用域没有嵌套。

如果它与第一次使用的范围不同,则可以在类或方法中重复使用相同的变量名。

在第一个示例中,两个变量具有相同的范围,因此名称冲突,编译器报告错误。 在你的第二个例子中,它们有不同的范围 – 一个在方法中,另一个在for循环中 – 因此没有冲突并且代码编译。

不同的范围;

 int variables = 3; .... int variables = 13; 

范围一致,肯定编译错误; 但

 for (;;;) {    int variables = 13; } 

每个周期等同于重新建立变量变量变量,然后随着范围的变化而消失; JVM堆栈框架就是这样一种机制(局部变量具有分配过程的开始,随着过程的结束而消除);

您可以将变量推送到数组中。

 Stack myarr = new Stack(); for (int i = 0; i < 10; i++) { int someInteger = 3; myarr.push(someInteger); } 

或者创建一个变量everyloop

 for (int i = 0; i < 10; i++) { int someInteger+i = 3; }