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

2022-09-04 08:13:48

这是我的代码:

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++) {
        }
    }
}

为什么编译但编译失败:foobar

Error: char cannot be dereferenced

两个循环声明之间的区别是什么,这使得循环在 foo 编译但 bar 失败?


答案 1

通过查看 JLS§14.14.2 对处理数组时增强型的工作原理的描述,我们可以看到差异:for

增强的 for 语句等效于以下形式的基本 for 语句:

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

请注意变量是如何在循环的主体中声明的,而不是在循环的标头中声明的。也就是说,您的函数如下所示: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];
        }
    }
}

这就是为什么你可以在增强型中摆脱阴影,而不是在传统的阴影中,这需要访问原始数组(以获取其,以获取的条目等)。forforlengthi

有关增强型循环的更多信息,请参阅 Java “for each” 循环如何工作?及其答案。for


答案 2

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

在基本语句 (§14.14.1) 的 ForInit 部分中声明的局部变量的作用域包括以下所有内容:for

  • 它自己的初始值设定项
  • 声明的 ForInit 部分中右侧的任何进一步声明符for
  • 语句的“表达式”“ForUpdate”部分for
  • 包含的声明

在增强语句 (§14.14.2) 的 FormalParameter 部分中声明的局部变量的作用域是包含的语句。for

(JLS 8,第 6.3 节)

这完美地解释了你观察到的行为:局部在基本循环的控制子句中(在其声明右侧的任何地方)中处于范围内,因此它在那里隐藏另一个,但在增强型循环中,它的作用域只是循环语句 - 它不在循环控制子句的任何地方。fooforfoofor