次のコードのコンパイルエラーが発生しました。
if(true)
int a = 10;
else
int b = 20;
次のコードに変更しても、コンパイルエラーは発生しません。
if(true) {
int a = 10;
}
else {
int b = 20;
}
なぜ最初の構文が間違っているのですか、そしてどの言語標準からですか?
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/
最初のコード例が言語設計にとって何を意味するかを分析しましょう
if(condition)
int a = 10;
else
int b = 20;
条件に応じて、a
またはb
を定義したことを意味します。どのブランチが使用されたかわからないので、ifステートメントの後にa
またはb
をどのように使用しますか?できません(できれば、奇妙なバグが発生する可能性があります)。
したがって、言語設計者として、これらの奇妙なバグを回避するために、a
とb
はそれぞれのブランチの外には表示されないと判断します。ただし、ブロックのないブランチは1つのステートメントしか持てないため、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 )は、すぐに囲むブロック内でのみ発生する可能性があることを繰り返します。
すべてのローカル変数宣言ステートメントは、すぐにブロックに含まれます。ローカル変数宣言ステートメントは、ブロック内の他の種類のステートメントと自由に組み合わせることができます。
JLS-14.4。ローカル変数宣言ステートメント 読み取り(一部)、
すべてのローカル変数宣言ステートメントは、すぐにブロックに含まれます。
そして
それ以外の場合は、結果の値に基づいて選択を行うことで実行が続行されます。
値がtrueの場合、含まれているステートメントが実行されます。 if-thenステートメントは、ステートメントの実行が正常に完了した場合にのみ正常に完了します。
値がfalseの場合、それ以上のアクションは実行されず、if-thenステートメントは正常に完了します。
ただし、 JLS-14.5。ステートメント には変数宣言は含まれていません。
シングルステートメントブロック(変数定義のみを含む)のスコープ内で2つの異なる変数を定義すると、両方に到達できなくなります。三項式で運が良かったと思います
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
に基づく値に初期化され、そのステートメントの後で到達可能であることに注意してください。
すべてのローカル変数宣言ステートメントは、すぐにブロックに含まれます。ローカル変数宣言ステートメントは、ブロック内の他の種類のステートメントと自由に組み合わせることができます。
これを読んでください http://docs.Oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.4
私の推測では、条件付きで変数を宣言することはできません。