103

Java スイッチについておかしな質問があります。

int key = 2;

switch (key) {
    case 1:
        int value = 1;
        break;
    case 2:
        value = 2;
        System.out.println(value);
        break;
    default:
        break;
}

シナリオ 1 -key値が 2 の場合、値が 2 として正常に 出力されます。
シナリオ 2 - コメントしようとすると、 The local variable value may not have been initializedと言ってスコークしvalue = 2ます。case 2:

質問:

シナリオ 1: 実行フローがcase 1:(のときにkey = 2) に進まない場合、どのようにして値変数の型を と認識しますintか?

シナリオ 2 : コンパイラが値変数の型を として認識している場合、コンパイラは.(宣言と初期化)の式にintアクセスしている必要があります。では、なぜそれはsqawrk なのですか?int value = 1;case 1:value = 2case 2:

4

6 に答える 6

118

基本的に、switch ステートメントはスコープの点で奇妙です。JLS のセクション 6.3から:

ブロック内のローカル変数宣言のスコープ (§14.4) は、宣言が表示されるブロックの残りの部分であり、独自の初期化子から始まり、ローカル変数宣言ステートメントの右側にさらに宣言子があればそれを含みます。

あなたの場合、実行されることはありませんcase 2が、同じブロック内にcase 1あり、その後に表示されます...したがって、論理的に宣言を「実行」しないにもかかわらずcase 1、ローカル変数はスコープ内にあり、書き込みに使用できます。(初期化は実行可能ですが、宣言は実際には「実行可能」ではありません。)

割り当てをコメントアウトしてvalue = 2;も、コンパイラは参照している変数を認識しますが、値を割り当てる実行パスを通過していないため、次のようにしようとするとエラーが発生します。明確に割り当てられていない他のローカル変数を読み取ります。

他のケースで宣言されたローカル変数を使用しないことを強くお勧めします。ご覧のとおり、非常に混乱するコードになります。switch ステートメントでローカル変数を導入するとき (これはめったにやろうとはしません - 理想的には、ケースは非常に短くする必要があります)、通常は新しいスコープを導入することを好みます。

case 1: {
    int value = 1;
    ...
    break;
}
case 2: {
    int value = 2;
    ...
    break;
}

これはより明確だと思います。

于 2012-05-30T06:12:04.680 に答える
22

変数は (int として) 宣言されていますが、初期化されていません (初期値が割り当てられています)。次の行を考えてみてください。

int value = 1;

として:

int value;
value = 1;

このint value部分は、コンパイル時にコンパイラに、int である value という変数があることを伝えます。パーツはvalue = 1それを初期化しますが、それは実行時に発生し、スイッチのそのブランチに入っていない場合はまったく発生しません。

于 2012-05-30T06:10:53.703 に答える
18

http://www.coderanch.com/t/447381/java-programmer-SCJP/certification/variable-initialization-within-case-blockから

宣言はコンパイル時に処理され、コードの実行フローには依存しません。valueは switch ブロックのローカル スコープ内で宣言されているため、その宣言の時点からそのブロック内のどこでも使用できます。

于 2012-05-30T06:10:13.153 に答える