Подтвердить что ты не робот

Почему я не могу определить переменную внутри цикла for таким образом?

Через тест я узнал, что

Это не является законным:

for (int i= 0; i < 1000000000; i++) 
    int j = i & i+1 ; // j cannot be declared here!

но это:

for (int i= 0; i < 1000000000; i++) { 
    int j = i & i+1 ;
}

Почему?

4b9b3361

Ответ 1

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

Во втором случае за циклом следуют фигурные скобки, которые создают новую область, и вы можете использовать переменную.

Ответ 2

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

Локальное объявление переменных не является оператором, это выражение о локальном переменном. Из приведенной ниже ссылки локальное объявление переменной может отображаться только как оператор внутри блока. (Блок представляет собой пару фигурных скобок, содержащих утверждения и декларации.)

for (int i= 0; i < 1000000000; i++) 
    int j = i & i+1 ; // Local variable j declaration not within a block ==> ERROR


for (int i= 0; i < 1000000000; i++) { 
    int j = i & i+1 ; // Local variable j declaration within a block ==> NO ERROR
}

Цитата из 14.4. Локальные заявления о декларации переменных:

...

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

...

И из 14.2. Блоки:

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

 Block:
   { BlockStatementsopt }

 BlockStatements:
   BlockStatement
   BlockStatements BlockStatement

 BlockStatement:
   LocalVariableDeclarationStatement
   ClassDeclaration
   Statement

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


Кроме того, это поведение не ограничивается Java. Вы заметили бы ошибку в подобной ситуации даже в C:

for(int i=0; i<=100; i++)
  int j = i;     /* Error: error: expected expression before 'int' */

for(int i=0; i<=100; i++) {
  int j = i;     /* Perfect */
}

Ответ 3

Локальное объявление переменных не допускается как один оператор для любой из грамматических конструкций, которые позволяют использовать один оператор вместо блока. Итак for, while, if и т.д.

Как он сломается (немного перефразированный), у вас есть for statement:

for (...;...;...) Statement

Где Statement может включать:

  • Блок

  • ExpressionStatement

An ExpressionStatement - это то, что вы можете использовать, когда у вас есть только один оператор, но LocalVariableDeclarationStatement - это BlockStatement.

Как заметил @RohitJain, было бы особенно полезно иметь только объявление переменной как единый оператор цикла.