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

Область переменных Java в выражении if

Я получил ошибку компиляции для следующего кода:

if(true)
    int a = 10;
else
    int b = 20;

Если я изменю его на следующий код, то ошибки компиляции не будет:

if(true) {
    int a = 10;
}
else {
    int b = 20;
}

Почему первый синтаксис неверен и с какого языка?

4b9b3361

Ответ 1

В спецификации Java указано, что оператор if-then-else имеет следующую форму:

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

Где Statement и StatementNoShortIf могут быть разные вещи, включая блоки (код, окруженный скобками), назначения (уже объявленным переменным), другие операторы if и т.д.

Следует отметить, что в этом списке отсутствуют инструкции объявления (например, int a; или int a = 10;), поэтому вы получаете ошибку компиляции.

Для полного списка вы можете прочитать спецификацию Java здесь: http://docs.oracle.com/javase/specs/

Ответ 2

Давайте проанализируем, что ваш первый пример кода будет означать для дизайна языка

if(condition)
    int a = 10;
else
    int b = 20;

Либо это означает, что в зависимости от условия мы определили a или b. Поскольку мы не знаем, какая ветка была взята, как мы используем либо a, либо b после if-statement? Мы не можем (и если бы мы могли это, вероятно, приводили бы к странным ошибкам).

Итак, как разработчики языка, мы решили, что a и b не видны за пределами их соответствующих ветвей, чтобы избежать этих странных ошибок. Но поскольку блочная ветка может иметь только один оператор, мы объявили a (или b) только для того, чтобы быть снова недоступным/непригодным для использования, поэтому это не имеет смысла. Поэтому мы решаем, что объявление переменной разрешено только с блоком. Блок может иметь несколько операторов, поэтому переменные, объявленные в этом блоке, могут использоваться этими другими операторами.

Дизайнеры Java, вероятно, применяли подобные рассуждения, поэтому они решили разрешить объявление только в блоке. Это делается с помощью определения if (JLS 14.9):

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

Statement (JLS 14.5)

Statement:
    StatementWithoutTrailingSubstatement
    ...

StatementNoShortIf:
    StatementWithoutTrailingSubstatement
    ...

StatementWithoutTrailingSubstatement:
    Block
    ...

Block (JLS 14.2):

Block:
    { [BlockStatements] }

BlockStatements:
    BlockStatement {BlockStatement}

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement

И LocalVariableDeclarationStatement (JLS 14.4), который повторяет, что это может произойти только в пределах непосредственно входящего блока:

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

Ответ 3

JLS-14.4. Локальные заявления о декларации переменных читает (частично),

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

и

JLS-14.9. Если Statmenets

В противном случае выполнение продолжается путем выбора на основе полученного результата:

Если значение равно true, то выполняется исполняемый оператор; инструкция if-then выполняется нормально тогда и только тогда, когда выполнение Statement завершается нормально.

Если значение false, никаких дальнейших действий не предпринимается, и инструкция if-then завершается нормально.

Однако JLS-14.5. Заявления не содержат объявления переменных.

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

int a = (condition) ? 10 : 20;

или

int a;
if (condition)
    a = 10;
else
    a = 20;

или

int a;
if (condition) {
    a = 10;
} else {
    a = 20;
}

Обратите внимание, что переменная a затем инициализируется значением, основанным на condition, и после этой инструкции оно доступно.

Ответ 4

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

Прочтите это http://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.4

Ответ 5

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

  • Если у вас нет фигурных скобок, вы пытаетесь объявить переменную условно во внешней области, которая не разрешена.
  • Когда вы добавляете фигурные скобки, вы создаете переменные в этой локальной области (которые не могут использоваться за пределами этих скобок).