在阴影方面,Java中的每个循环和传统for循环之间有什么区别?

Kor*_*gay 13 java foreach for-loop

这是我的代码:

class HelloWorld {

    char[] foo = {'a', 'b'};

    // This will compile
    void foo() {
        for (char foo : foo) {
        }
    }

    // This will not compile
    void bar() {
        for (char foo = 0; foo < foo.length; foo++) {
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何foo编译但编译bar失败:

Error: char cannot be dereferenced
Run Code Online (Sandbox Code Playgroud)

在foo编译中使循环失败的两个循环声明之间有什么区别?

T.J*_*der 15

我们可以通过查看JLS§14.14.2for处理数组时增强功能如何工作的描述来看到差异:

增强的for语句相当于表单的基本for语句:

T[] #a = Expression;
L1: L2: ... Lm:
for (int #i = 0; #i < #a.length; #i++) {
    {VariableModifier} TargetType Identifier = #a[#i];
    Statement
}
Run Code Online (Sandbox Code Playgroud)

注意变量是如何在循环体内声明的,而不是循环的标题.也就是说,你的foo功能是这样的:

void foo() {
    { // Freestanding block for scope, though not really needed as `foo` has
      // nothing else in it
        char[] a = foo;       // T[] #a = Expression;
        for (int i = 0; i < a.length; i++) {
            char foo = a[i];  // {VariableModifier} TargetType Identifier = #a[#i];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这就是为什么你在增强的for,而不是传统的for,需要访问原始数组(获取它length,获取条目i等)中的阴影.

关于增强for循环的更多信息"每个'循环的Java'如何工作?及其答案.


Joh*_*ger 8

Java语言规范以不同的方式定义了两者的范围char foo:

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

  • 它自己的初始化程序
  • 任何进一步的说明符在右边ForInit的部分for语句
  • 表达ForUpdate的部分for语句
  • 包含的声明

在增强语句(第14.14.2节)的FormalParameter部分中声明的局部变量的范围for是包含的Statement.

(JLS 8,第6.3节)

这完美地解释了你观察到的行为:本地foo在基本for循环的控制子句中的范围内(在其声明的右边的任何地方),因此它在foo那里影响另一个,但在增强for循环中它的范围只是循环语句 - - 它不在循环控制子句中的任何位置.