вопрос о переменной области и теневого копирования в Java - PullRequest
4 голосов
/ 07 января 2011

У меня такая ситуация, которую я не могу понять о слежке. Например, следующий код

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?
   }
}

Спасибо за терпение.

Ответы [ 6 ]

12 голосов
/ 07 января 2011

Вы можете сделать теневую локальную переменную экземпляром / статической переменной, но нельзя сделать так, чтобы одна локальная переменная (ваш счетчик цикла) затеняла другую локальную переменную или параметр (ваш параметр).

Из спецификации языка Java, раздел 14.4.3 :

Если имя, объявленное как локальная переменная, уже объявлено как имя поля, то это внешнее объявление затеняется (§6.3.1) во всей области действия локальной переменной.

Обратите внимание на часть «имя поля» - она ​​указывает, что это должно быть поле , которое затенено.

А из раздел 8.4.1 :

Область действия параметра метода (§8.4.1) или конструктора (§8.8.1) - это все тело метода или конструктора.

Эти имена параметров не могут быть повторно объявлены как локальные переменные метода или как параметры исключений в предложениях catch в операторе try метода или конструктора.

(Далее говорится о локальных классах и анонимных классах, но они не имеют отношения к вашему случаю.)

2 голосов
/ 07 января 2011
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;
} 

См. Также

1 голос
/ 07 января 2011

Область действия переменной также зависит от иерархии блока.

т.е. если вы используете вот так

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.

   }

То есть, если переменная объявлена ​​во внешнем блокетогда вы не можете объявить то же самое в блоке, который является внутренним.другой способ сделать это.

0 голосов
/ 07 января 2011

Это не затенение, это конфликт здесь.Оба a находятся в области действия метода.Нельзя определить две переменные с одинаковыми именами в одной и той же области видимости.

0 голосов
/ 07 января 2011

Проблема не в том, что цикл скрывает поле класса, имя уже используется параметром.

Два варианта: один - изменить цикл:

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

Используется параметр в качестве индексной переменной. Непонятно, зачем вам параметр, но все равно ...

Другой вариант - переименовать переменную цикла или параметр в другое значение.

0 голосов
/ 07 января 2011

Но вы не объявляете второе «а» в этой новой области видимости, как показывает ваш код.Он входит в объем самого блока goFoo ().

...