コンパイルしようとすると
for(;;)
{
}
System.out.println("End");
Java コンパイラは、次のエラーを生成しますUnreachable statement
。しかし、別の「到達不能」(私によると)break
ステートメントを追加して、次のようにします。
for(;;)
{
if(false) break;
}
System.out.println("End");
コンパイルします。エラーが発生しないのはなぜですか?
コンパイルしようとすると
for(;;)
{
}
System.out.println("End");
Java コンパイラは、次のエラーを生成しますUnreachable statement
。しかし、別の「到達不能」(私によると)break
ステートメントを追加して、次のようにします。
for(;;)
{
if(false) break;
}
System.out.println("End");
コンパイルします。エラーが発生しないのはなぜですか?
同様の質問に対する私の回答で説明したように、特定の構成要素if(compile-time-false)
は、明示的なバックドアとして到達不能ルールから除外されます。この場合、コンパイラは yourbreak
を到達可能として扱います。
JLSから
if-then ステートメントは、次の少なくとも 1 つが true の場合に正常に完了できます。
> if-then ステートメントは到達可能であり、条件式は値が true である定数式ではありません。
> then ステートメントは正常に完了できます。
だからif(false)
許される。
この「条件付きコンパイル」機能は、バイナリ互換性に大きな影響を与え、関係があります。このような「フラグ」変数を使用する一連のクラスがコンパイルされ、条件付きコードが省略されている場合、後でフラグの定義を含むクラスまたはインターフェイスの新しいバージョンを配布するだけでは十分ではありません。したがって、フラグの値の変更は、既存のバイナリとバイナリ互換性がありません。(switch ステートメントの case ラベルでの定数の使用など、このような非互換性には他の理由もあります;)
基本的には、実際にコードを実行せずにプログラムを静的に解析することで到達不能コードを検出します。条件は実行時にチェックされます。したがって、この分析が行われるとき、実際に状態を調べるのではなく、経由でアクセス可能 (到達可能) であることを確認するだけです。 break;
if