Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 增强for循环中局部变量的范围_Java_Foreach_Scope - Fatal编程技术网

Java 增强for循环中局部变量的范围

Java 增强for循环中局部变量的范围,java,foreach,scope,Java,Foreach,Scope,关于变量范围,我有一个相当简单的问题 我熟悉增强的For循环,但不明白为什么我应该声明一个新变量来保留每个元素。一个例子可以澄清我的问题: 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 fi

关于变量范围,我有一个相当简单的问题

我熟悉增强的For循环,但不明白为什么我应该声明一个新变量来保留每个元素。一个例子可以澄清我的问题:

        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);
        }
那么为什么我要声明这个新变量呢?毕竟,
i
可以在for循环中访问。我不想使用
I
的任何以前的值,只是不想声明一个新变量。(我猜对于其他iterable项目,使用相同的变量可能会更快)

我想这就是增强For循环的构建方式,但这是否打破了整个范围的想法

上述行为引发了一个问题。编译器是对整个
for
循环使用相同的变量,只是更新其值,还是为每次迭代创建一个新变量

有趣的是,如果我保留int I的声明(在
for
循环之前和内部),我甚至会得到一个编译器错误

重复局部变量i

这让(至少对我来说)事情有点奇怪。因此,我不能在
for
循环中使用先前声明的变量
I
,但也不能在循环中使用相同名称声明新变量

那么为什么我要声明这个新变量呢

因为这就是语法的定义方式

毕竟,我在for循环中是可以访问的

这就是语义学。这与语法无关

我不想使用I的任何以前的值,只是不想声明一个新变量。(我猜对于其他iterable项目,使用相同的变量可能会更快)

不要猜测性能。测试和测量。但在这种情况下,没有什么可测量的,因为任何工作代码都比任何非工作代码快

这是否意味着我有一个局部变量,在每个循环中获得不同的值或不同的变量

从语言的角度来看,每次迭代都有不同的变量。这就是为什么你可以写:

for(final ItemType item: iterable) {
  …
}
这有很大的不同,因为您可以在引用当前元素的循环中创建内部类实例。在Java8中,您也可以使用lambdas,甚至可以省略
final
修饰符,但语义不会改变:您不会得到像C#中那样令人惊讶的结果

我猜对于其他iterable项目,使用相同的变量可能会更快

那是胡说八道。只要您不知道生成的代码看起来是什么样子,就不应该猜测


但是,如果您对Java字节码的细节感兴趣:在堆栈框架中,局部变量是通过数字而不是名称来处理的。通过重用超出范围的局部变量存储,程序的局部变量映射到这些存储位置。无论变量是在整个循环中存在,还是在每次迭代中“重新创建”,都没有区别。它仍将仅占用堆栈帧中的一个插槽。因此,试图在源代码级别上“重用局部变量”毫无意义。它只会降低程序的可读性。

程序中的
int i
对相同范围下的for循环和它下面的其他for循环(如果存在)可见。但是,
for(inti:ar)
中的i是for循环的局部。因此,一旦循环的执行结束,就结束了。这是为foreach循环定义的语法,即“必须使用范围限于循环的变量”


如果您反复使用同一个变量微小的原始变量,而不是仅在需要时创建一个在循环结束后被销毁的变量,那么为什么会有显著的性能优势。

这里只提供参考:定义了增强的for循环,使其具有以下结构(与此问题相关):


其中可以概括为“a类型”(原语、引用…)。因此,根据语言规范,给出循环变量的类型是必须的,这导致了问题中描述的观察结果(无可否认:有些混乱)。

我认为除了声明这是语法之外,没有人回答过原始问题。我们都知道这就是语法。从逻辑上讲,问题是为什么?
毕竟,只要循环是非增强型for循环,就可以使用在循环之前定义的变量作为循环变量

是的,不同的循环意味着不同的作用域,这意味着本质上不同的变量。投票重新打开“这是否意味着我有一个局部变量,在每个循环中获得不同的值或不同的变量”是一个有趣的问题。OP可能想编辑问题以强调这一部分:)JLS每次都会说一个新变量。然而,作用域只是循环的主体,因此我可以想象编译器在后台重用相同的变量。但我不知道如何检查它。@Ordous:你说得对,变量(或其存储位置)是在后台重用的。您不需要手动验证,因为JVM验证器已经为您完成了这项工作:循环的向后跳转必须以与源代码具有相同堆栈布局的代码位置为目标。JVM堆栈不允许在每次迭代中增长。这个问题的完美答案奇怪的是,这个答案被接受了。它没有开始回答这个问题。我同意这个答案没有用,而且答案的语气太刺耳。问题是“为什么”,我已经回答了。很好地解释了为什么语法是这样定义的。
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).
 EnhancedForStatement:
   for ( {VariableModifier} UnannType VariableDeclaratorId : Expression ) Statement