Область переменных Java в выражении if
Я получил ошибку компиляции для следующего кода:
if(true)
int a = 10;
else
int b = 20;
Если я изменю его на следующий код, то ошибки компиляции не будет:
if(true) {
int a = 10;
}
else {
int b = 20;
}
Почему первый синтаксис неверен и с какого языка?
Ответы
Ответ 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
Мое лучшее предположение заключается в том, что вы не можете условно объявлять переменные.
- Если у вас нет фигурных скобок, вы пытаетесь объявить переменную условно во внешней области, которая не разрешена.
- Когда вы добавляете фигурные скобки, вы создаете переменные в этой локальной области (которые не могут использоваться за пределами этих скобок).