关于java中变量范围和阴影的问题

我遇到这种情况我无法理解阴影。 例如以下代码

class Foo { int a = 5; void goFoo(int a) { // No problem naming parameter as same as instance variable for (int a = 0; a < 5; a++) { } //Now the compiler complains about the variable a on the for loop // i thought that the loop block had its own scope so i could shadow // the parameter, why the compiler didnt throw an error when i named // the parameter same as the instance variable? } } 

谢谢你耐心等待。

您可以使局部变量阴影成为实例/静态变量 – 但是您不能使一个局部变量(您的循环计数器)影响另一个局部变量或参数(您的参数)。

从Java语言规范, 第14.4.3节 :

如果声明为局部变量的名称已经声明为字段名称,那么该外部声明将在局部变量的整个范围内被遮蔽(第6.3.1节)。

注意“字段名称”部分 – 它指定它必须是一个被遮蔽的字段

从第8.4.1节开始 :

方法(第8.4.1节)或构造函数(第8.8.1节)的参数范围是方法或构造函数的整个主体。

这些参数名称不能重新声明为方法的局部变量,也不能重新声明为方法或构造函数的try语句中的catch子句的exception参数。

(它继续讨论本地类和匿名类,但它们与你的情况无关。)

 void goFoo(int a) { for (int a = 0; a < 5; a++) { } } 

它类似于

 void goFoo() { int a; for (int a = 0; a < 5; a++) { } } 

所以在同一范围内多次声明a ,这是不可接受的。

或者只是它类似于

 void goFoo() { int a; int a; } 

另见

  • java的可变范围,遮蔽

变量的范围也取决于块的层次结构。

即如果你这样使用

 void goFoo(int a) { // No problem naming parameter as same as instance variable for (int b = 0; b < 5; b++) { } //Now the compiler complains about the variable a on the for loop // i thought that the loop block had its own scope so i could shadow // the parameter, why the compiler didnt throw an error when i named // the parameter same as the instance variable? int b; // you can do this. } 

也就是说,如果在外部块中声明了变量,那么就不能在内部的块中声明相同的内容。 另一种方式你可以做到这一点。

但是,如您的代码所示,您不会在该新范围中声明第二个“a”。 它位于goFoo()块本身的范围内。

问题不在于循环正在遮蔽类字段,该名称已被参数使用。

两个选项:一个是改变循环:

 for (a = 0; a < 5; a++) { } 

这使用参数作为索引变量。 不清楚为什么你会有一个参数,但都是一样的......

另一个选项是将循环变量或参数重命名为其他内容。

这不是影子,这是一场冲突。 两者都在方法范围内。 无法在同一范围内定义两个同名变量。