4

我遇到了这种情况,我无法理解阴影。例如下面的代码:

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 didn't throw an error when i named
       // the parameter same as the instance variable?
   }
}
4

7 回答 7

14

您可以使局部变量遮蔽实例/静态变量 - 但不能使一个局部变量(您的循环计数器)遮蔽另一个局部变量或参数(您的参数)。

来自 Java 语言规范,第 14.4.3 节

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

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

第 8.4.1 节开始:

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

这些参数名称可能不会被重新声明为方法的局部变量,或者作为方法或构造函数的 try 语句中的 catch 子句的异常参数。

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

于 2011-01-07T07:25:21.060 回答
2
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;
} 

另见

于 2011-01-07T07:25:02.093 回答
1

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

即如果你这样使用

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.

   }

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

于 2011-01-07T07:25:37.323 回答
0

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

于 2011-01-07T07:25:17.327 回答
0

问题不在于循环隐藏了类字段,该名称已被参数使用。

两种选择:一种是改变循环:

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

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

另一种选择是将循环变量或参数重命名为其他名称。

于 2011-01-07T07:25:58.347 回答
0

这不是阴影,而是这里的冲突。两者a都在方法范围内。不能在同一范围内定义两个同名的变量。

于 2011-01-07T07:28:23.860 回答
0

在 Java 中(与 C++ 不同),当另一个同名的局部变量在“范围内”时,您不能声明一个局部变量。

你不能在 Java 中做到这一点

void foo() {
    int a;
    {
         int a;  // You cannot declare 'a' here because a
                 // from the outer block is still in scope
                 // here. Local variables in Java cannot be
                 // shadowed by another local variable with
                 // the same name. Only instance variables 
                 // can be shadowed by the local variables 
                 // with the same name.
    }
}

然而 c++ 允许你这样做

void foo()
{
    int a;
    a = 10;
    cout << a << endl;  // prints 10 duh
    {
        int a;   // this declaration shadows the local
                 // variable 'a' from the outer scope.

        a = 20;  // assigns 20 to the variable 'a' in
                 // current inner scope, like you'd expect.
        cout << a << endl;  // prints 20.
    }
    cout << a << endl;  // prints 10
}
于 2021-07-15T11:41:40.703 回答