Повторное объявление переменных внутри циклов в Java

в Java мы не можем объявить переменную в той же области с другой переменной, которая имеет то же имя:

int someInteger = 3;

...

int someInteger = 13;

синтаксическая ошибка, не компилируется. Однако, если мы поместим его в цикл:

for (int i = 0; i < 10; i++) {
   int someInteger = 3;
}

не генерирует ошибок, работает очень хорошо. Мы в основном объявляем одну и ту же переменную. В чем причина? Какова логика, которую я не знаю/не понимаю за этим?

7 ответов


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

вы также можете сделать это, по той же причине

        {
           int someInteger = 3;
        }
        {
           int someInteger = 13;
        }

кстати, Java не разрешает затенение локальных переменных, что может быть неудобно

        int x = 3;
        {
           int x = 13; // error!
        }

        Consumer<Integer> consumer = (x)->print(x);  // ERROR! 
        // lambda parameter is treated like local variable

        Runnable r = ()->{ int x; ... } // ERROR
        // lambda body is treated like local block

Java имеет то, что называется "областью действия блока", что означает, что любой блок кода (определенный заключительными фигурными скобками) объявлена переменная, которая (и только там) там, где она существует. Это также означает, что каждая переменная может быть объявлена только один раз в любой момент заблокировать.

когда вы говорите

for (int i = 0; i < 10; i++) {
  int someInteger = 3;
}

новый блок создается на каждой итерации. Это похоже на высказывание

{ 
  int someInteger = 3;
}
{ 
  int someInteger = 3;
}
...

в этом случае существует только 1 переменная с именем someInteger в каждом блок.

когда вы говорите

{ 
  int someInteger = 3;
  ...
  int someInteger = 3;
}

компилятор правильно жалуется, что вы объявляете более одной переменной с тем же именем в одном блоке (или области) кода.


в пределах блока, новый и тени лексико масштабы другие someInteger. Запись "Википедии" о переменной тенизации говорит (частично)

переменной тенизации происходит, когда переменная, объявленная в определенной области (блок решений, метод или внутренний класс), имеет то же имя, что и переменная, объявленная во внешней области. На уровне идентификаторов (имен, а не переменных) это известный как имя для маскировки.


каждая переменная имеет область видимости. Область вложена в скобку {}. когда вы выходите из этой области, этот контекст отсутствует, поэтому вы можете определить другие переменные с тем же именем. Иначе вы не сможете.

приведу два примера:

// define new scope named "methodA"
public void methodA() {
   int a = 3; 
   // define new scope named "loop"
   for (int i = 0; i < 10; i++) {
      int a = 6; // ERROR
   }
}

в вышеуказанном случае, вы встретите ошибку. поскольку область " цикл "находится внутри области" methodA", поэтому первое определение все еще существует, когда вы переходите к области" цикл".

второй случай:

// define new scope named "methodA"
public void methodA() {
   // define new scope inside methodA scope
   {
       int a = 3;
   } 
   // define new scope named "loop"
   for (int i = 0; i < 10; i++) {
      int a = 6; // NO ERROR
   }
}

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


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

в вашем первом примере две переменные имеют одинаковую область действия и, следовательно, имя конфликтует, и компилятор сообщает об ошибке. Во втором примере они имеют другую область-один находится в методе, другой - в цикле for-следовательно, нет столкновения, и код компилируется.


разных областей;

int variables = 3;
....
int variables = 13;

объем единогласно, конечно, ошибка компиляции; Но!--3-->

for (;;;) {
     int variables = 13;
}

каждый цикл эквивалентен восстановлению переменных переменных переменных, прежде чем исчезнуть с изменением области; Фрейм стека JVM - это такой механизм (локальные переменные с началом процесса назначения, с окончанием процесса и устранением);


вы можете поместить свою переменную в массив.

Stack myarr = new Stack();
for (int i = 0; i < 10; i++) {
   int someInteger = 3;
myarr.push(someInteger);
}

или создайте переменную everyloop

for (int i = 0; i < 10; i++) {
   int someInteger+i = 3;
}