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

时间:2017-04-04 17:23:29

标签: java for-loop foreach

这是我的代码:

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

foo如何编译,但编译bar失败的原因为:

Error: char cannot be dereferenced

在foo编译中生成循环但是bar失败的两个循环声明之间有什么区别?

2 个答案:

答案 0 :(得分:15)

我们可以通过查看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
}

注意变量是如何在循环的 body 中声明的,而不是循环的标题。也就是说,您的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];
        }
    }
}

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

有关How does the Java 'for each' loop work?中增强的for循环及其答案的详情。

答案 1 :(得分:8)

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

  

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

     
      
  • 自己的初始化程序
  •   
  • for声明的 ForInit 部分右侧的任何其他声明符
  •   
  • for声明的表达式 ForUpdate 部分
  •   
  • 包含的声明
  •   
     

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

JLS 8, section 6.3

这完美地解释了您观察到的行为:本地foo在基本for循环的控制子句中的范围内(声明右侧的任何地方),因此它会影响另一个foo 1}}但是在增强的for循环中,它的作用域只是循环语句 - 它不在循环控制子句中的任何位置。