web-dev-qa-db-ja.com

Java ifステートメントの変数スコープ

次のコードのコンパイルエラーが発生しました。

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

次のコードに変更しても、コンパイルエラーは発生しません。

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

なぜ最初の構文が間違っているのですか、そしてどの言語標準からですか?

33
Orup

Java仕様では、if-then-elseステートメントの形式は次のとおりです。

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

ここで、StatementStatementNoShortIfは、ブロック(中括弧で囲まれたコード)、割り当て(すでに宣言された変数への)、その他のifステートメントなどを含むさまざまなものです。

注目すべきは、その宣言ステートメント(例:int a;またはint a = 10;)がそのリストにないため、コンパイルエラーが発生します。

完全なリストについては、Java仕様をここで読むことができます: http://docs.Oracle.com/javase/specs/

27
sunil

最初のコード例が言語設計にとって何を意味するかを分析しましょう

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

条件に応じて、aまたはbを定義したことを意味します。どのブランチが使用されたかわからないので、ifステートメントの後にaまたはbをどのように使用しますか?できません(できれば、奇妙なバグが発生する可能性があります)。

したがって、言語設計者として、これらの奇妙なバグを回避するために、abはそれぞれのブランチの外には表示されないと判断します。ただし、ブロックのないブランチは1つのステートメントしか持てないため、a(またはb)はすぐに到達不能/使用不能になると宣言しただけなので、それは意味がありません。そのため、変数宣言はブロックでのみ許可されると判断しました。ブロックには複数のステートメントを含めることができるため、そのブロックで宣言された変数を他のステートメントで使用できます。

Javaの設計者はおそらく同様の推論を適用したため、ブロック内の宣言のみを許可することにしました。これはifJLS 14.9 ):

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

StatementJLS 14.5

Statement:
    StatementWithoutTrailingSubstatement
    ...

StatementNoShortIf:
    StatementWithoutTrailingSubstatement
    ...

StatementWithoutTrailingSubstatement:
    Block
    ...

BlockJLS 14.2 ):

Block:
    { [BlockStatements] }

BlockStatements:
    BlockStatement {BlockStatement}

BlockStatement:
    LocalVariableDeclarationStatement
    ClassDeclaration
    Statement

そして、LocalVariableDeclarationStatementJLS 14.4 )は、すぐに囲むブロック内でのみ発生する可能性があることを繰り返します。

すべてのローカル変数宣言ステートメントは、すぐにブロックに含まれます。ローカル変数宣言ステートメントは、ブロック内の他の種類のステートメントと自由に組み合わせることができます。

19
Mark Rotteveel

JLS-14.4。ローカル変数宣言ステートメント 読み取り(一部)、

すべてのローカル変数宣言ステートメントは、すぐにブロックに含まれます。

そして

JLS-14.9。Statmenetsの場合

それ以外の場合は、結果の値に基づいて選択を行うことで実行が続行されます。

値が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;
}

次に、変数aconditionに基づく値に初期化され、そのステートメントの後で到達可能であることに注意してください。

13
Elliott Frisch

すべてのローカル変数宣言ステートメントは、すぐにブロックに含まれます。ローカル変数宣言ステートメントは、ブロック内の他の種類のステートメントと自由に組み合わせることができます。

これを読んでください http://docs.Oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.4

6
Lalith J.

私の推測では、条件付きで変数を宣言することはできません。

  • 中括弧がない場合、外部スコープで条件付きで変数を宣言しようとしていますが、これは許可されていません。
  • 中かっこを追加すると、そのローカルスコープに変数が作成されます(中かっこ以外での使用は許可されていません)。
0
Juan Mendes