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



这是我的代码:

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 失败的两个循环声明之间有什么区别?

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

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

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

Java 语言规范对两个char foo的作用域的定义不同:

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

  • 它自己的初始值设定项
  • for声明的ForInit部分右侧的任何其他声明符
  • for语句的表达式ForUpdate部分
  • 包含的声明

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

(JLS 8,第6.3节)

这完美地解释了您观察到的行为:本地foo在基本for循环的控制子句的范围内(在其声明右侧的任何位置),因此它在那里隐藏其他foo,但在增强for循环中,它的作用域只是循环语句 - 它不在循环控制子句的任何范围内。

最新更新