简体   繁体   English

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

[英]scope of local variable in enhanced for-loop

I have a rather simple question about variable scope. 关于变量范围,我有一个相当简单的问题。

I am familiar with the Enhanced For-Loops but I do not get why I should declare a new variable to keep each element. 我熟悉增强的For-Loops,但我不明白为什么我应该声明一个新变量来保存每个元素。 One example might clarify my question: 一个例子可能澄清我的问题:

        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);
        }

So why I should declare this new variable? 那么我为什么要声明这个新变量呢? After all i is accessible inside the for loop. 毕竟i可以在for循环中访问。 I did not want to use any previous value of i , just did not want to declare a new variable. 我不想使用任何以前的i值,只是不想声明一个新变量。 (I guessed for other iterable items it might be faster using the same variable). (我猜测其他可迭代项目使用相同的变量可能会更快)。

I guess that's how Enhanced For-Loops were built but does not this break the whole scope idea? 我想这就是增强For For-Loop的构建方式,但这不会打破整个范围的想法吗?

There is a question rising from the above behavior. 上述行为引发了一个问题。 Whether the compiler uses the same variable for the whole for loop and just updates its value or it creates a new variable for each iteration? 编译器是否对整个for循环使用相同的变量并只更新其值,或者为每次迭代创建一个新变量

An interesting part is that if I keep both declaration of int i (before and inside the for loop) I even get a compiler error about 一个有趣的部分是,如果我保留int i的声明(在for循环之前和之内),我甚至会得到编译器错误

Duplicate local variable i 重复的局部变量i

which makes (at least for me) things a bit more strange. 这使得(至少对我来说)事情有点奇怪。 So I cannot use the previous declared variable i inside the for loop but neither can I declare a new one inside it with the same name. 所以我不能在for循环中使用先前声明的变量i for但我也不能在其中声明一个具有相同名称的新变量。

So why I should declare this new variable? 那么我为什么要声明这个新变量呢?

Because that's the way the syntax is defined. 因为这是定义语法的方式。

After all i is accessible inside the for loop. 毕竟我可以在for循环中访问。

That's semantics. 这是语义。 It's irrelevant to syntax. 这与语法无关。

I did not want to use any previous value of i, just did not want to declare a new variable. 我不想使用任何以前的i值,只是不想声明一个新变量。 (I guessed for other iterable items it might be faster using the same variable). (我猜测其他可迭代项目使用相同的变量可能会更快)。

Don 't guess about performance. 不要猜测性能。 Test and measure. 测试和测量。 But in this case there's nothing to measure, because any working code is faster than any non-working code. 但在这种情况下,没有什么可衡量的,因为任何工作代码都比任何非工作代码更快。

Does this means that I have a local variable that gets different values or a different variable in each loop? 这是否意味着我有一个局部变量在每个循环中获得不同的值或不同的变量?

From a language point of view you have a different variable in each iteration. 从语言的角度来看,每次迭代都有一个不同的变量。 That's why you can write: 这就是为什么你可以写:

for(final ItemType item: iterable) {
  …
}

which makes a great difference as you can create inner class instances within the loop referring to the current element. 因为你可以在循环中创建引用当前元素的内部类实例,这会产生很大的不同。 With Java 8 you can use lambdas as well and even omit the final modifier but the semantic does not change: you don't get the surprising results like in C#. 使用Java 8,您也可以使用lambda,甚至可以省略final修饰符,但语义不会改变:您不会像在C#中那样获得令人惊讶的结果。

I guessed for other iterable items it might be faster using the same variable 我猜测其他可迭代项目使用相同的变量可能会更快

That's nonsense. 那是胡说八道。 As long as you don't have a clue of how the produced code looks like you shouldn't even guess. 只要您不知道生成的代码是如何形成的,您甚至不应该猜测。

But if you are interested in the details of Java byte code: within a stack frame local variables are addressed by a number rather than by a name. 但是如果您对Java字节代码的细节感兴趣:在堆栈框架内,局部变量由数字而不是名称来寻址。 And the local variables of your program are mapped to these storage locations by reusing the storage of local variables that went out of scope. 并且通过重用超出范围的局部变量的存储,将程序的局部变量映射到这些存储位置。 It makes no difference whether the variable exists during the entire loop or is “recreated” on every iteration. 变量在整个循环期间是存在还是在每次迭代时“重新创建”都没有区别。 It will still occupy just one slot within the stack frame. 它仍然只占用堆栈帧中的一个插槽。 Hence, trying to “reuse local variables” on a source code level makes no sense at all. 因此,尝试在源代码级别上“重用局部变量”根本就没有意义。 It just makes your program less readable. 它只会降低程序的可读性。

Just to have the reference here: The JLS Section 14.14.2, The enhanced for statement defines the enhanced for-loop to have the following structure (relevant for this question): 只是在这里引用: JLS Section 14.14.2,增强的for语句定义了增强的for循环,它具有以下结构(与此问题相关):

  EnhancedForStatement: for ( {VariableModifier} UnannType VariableDeclaratorId : Expression ) Statement 

where UnannType can be summarized to be "a type" (primitive, reference...). 其中UnannType可以概括为“类型”(原始,引用...)。 So giving the type of the loop variable is simply obligatory according to the language specification - causing the (admittedly: somewhat confusing) observations described in the question. 因此根据语言规范给出循环变量的类型是必须的 - 导致问题中描述的(不可否认的:有些混乱)观察。

The int i in the program is visible to the for loop and maybe other for loops beneath it (if present) under the same scope. 程序中的int i对于for循环是可见的,并且在同一范围内可能是其下面的循环(如果存在)。 But the i inside the for(int i : ar) is local to the for loop. 但是for(int i : ar)是for循环的本地。 Hence ending once the execution of loop is over. 因此,一旦循环的执行结束就结束。 Thats the syntax defined for foreach loop that "you have to use a variable with scope limited to the loop". 这是为foreach循环定义的语法,“你必须使用范围限于循环的变量”。

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).

Why would there be any considerable performance benefit if you use the same variable tiny primitive variable over and over versus creating a one only when needed and which gets destroyed after loop ends. 如果你反复使用相同的变量微小原始变量而不是仅在需要时创建一个变量并且在循环结束后被破坏,那么为什么会有相当大的性能优势呢?

I don't think anyone has answered the original question beyond just declaring that that is the syntax. 我认为除了宣称那是语法之外,没有人回答原始问题。 We all know that that is the syntax. 我们都知道这就是语法。 The question is, logically speaking, why? 从逻辑上讲,问题是,为什么? After all, you can use a variable defined just before a loop as the loop variable, as long as the loop is a non-enhanced for loop! 毕竟,只要循环是非增强的for循环,就可以使用在循环之前定义的变量作为循环变量!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM