今日、バグを30分検索した後、次のように、コードの代わりにifステートメントの後にセミコロンを付けることができることを発見しました。
if(a == b);
// Do stuff
これは基本的に、a
等しいかどうかに関係なく処理が行われることを意味しb
、if
ステートメントには何の意味もありません。Javaでエラーが発生しないのはなぜですか?これが役立つ状況はありますか?
今日、バグを30分検索した後、次のように、コードの代わりにifステートメントの後にセミコロンを付けることができることを発見しました。
if(a == b);
// Do stuff
これは基本的に、a
等しいかどうかに関係なく処理が行われることを意味しb
、if
ステートメントには何の意味もありません。Javaでエラーが発生しないのはなぜですか?これが役立つ状況はありますか?
Java言語仕様によると:
空のステートメント
空のステートメントは何もしません。
EmptyStatement: ;
空のステートメントの実行は常に正常に完了します
これは基本的に、a==bの場合に空のステートメントを実行することを意味します
if(a == b);
この問題には2つの主な解決策があります。
コードフォーマッタと、およびで囲まれたものを使用することで、空のステートメントの問題を回避if
でき{
ます}
。これを行うことにより、あなたの空のステートメントははるかに読みやすくなります。
if(a == b){
;
}
次のような静的コード分析に使用されるツールを確認することもできます。
彼らはこのような問題を即座に強調することができます。
両方のソリューションを組み合わせることをお勧めします。
これが役立つ状況はありますか?
使える?「コードをよりクリーンで、より明確で、より速く、より保守しやすくする」のように?全くない。これはおそらく貧弱で混乱を招くコードです。
しかし、それは必ずしも良性ではありません。このようなステートメントは、副作用を引き起こすメソッドによってアクションを実行したり、状態を変更したりできます。また、オプションで、演算子の短絡によってこれらのメソッドを評価できます。
if( a() && b() );
ここで、a()
またはb()
何かを行う可能性があり、trueのb()
場合にのみ実行されます。a()
理由については、答えはwhile(reader.read());
、開発者が悪いコードを書く代わりの方法よりも、定義された期待される動作(たとえば、のようなステートメント)から逸脱する方が悪いということだと思います。
悪いコードを書くことは常に可能です。繰り返しになりますが、これはほとんどの場合、悪いコードになります。
考えられる使用例:
if (a==b);
else {
// Do something
}
良くありませんが、可能です。
それでも、Java仕様では空のを許可しないようにする必要があると思いますif
。
Eclipse を使用している場合は、これらのステートメントについて警告するように設定できます。
ステートメントを使用する場合、条件が真であれば、if
後の最初のステートメントが実行されます。(中括弧付き)if
の後にブロックがある場合は、そのブロック全体にカウントされます。if
ブロックがない場合は、1つのステートメントのみにカウントされます。単一のセミコロンは空のステートメントです。次のように、例からコードを記述することもできます。
if(a==b) {
;
}
これは、式とステートメントを区別するための構文糖衣が多かった時代の古い名残りです。
基本的に、コンマはリスト項目の区切り記号として使用されていたため、セミコロンは「ステートメントのリスト」の区切り記号として使用されていました。欠点は、リスト内の null アイテムとブロック内の null ステートメントの処理にあります。
アイテムのリストでは、Java は明示的なキーワード を使用しnull
ますが、「null ステートメント」は単なる空行です。空行の存在を許可することは、C から継承された伝統の名残りです。
なぜそれをするのですか?特にif
ステートメントが実行されていないことがわかっているステートメントの場合: 一部の if ステートメントには副作用があるため:
int c;
if ((c = in.read()) != -1);
はい、これは最良の例ではありませんが、基本的には、ストリームから 1 バイトを読み取って何もしないと言います。いくつかのまれなケースでは役立つかもしれませんが、この例が最善でなくても、意図を示しています。ステートメントを誤って実行することなく、式の副作用を感じたいのです。
役に立つ機会は思いつかない。次のようなループに役立ちます
while(do something);
また
for(init; do something; something else);
IDEでコードのフォーマットを定期的に使用すると、この種のバグが明らかになります。一部のIDEは、これもバグの可能性があると強調しています。
私はあなたに同意しますが、これには人間にとって有用な目的はありません。言語定義を単純化するので、そこにあるのではないかと思います。if
たとえば、aの後に続くものはeの後に続くものと同じであることを意味しwhile
ます。
なんで?これは、コンパイラの作成者にとって簡単だからです。後にセミコロンをチェックするために特別なケースを作成する必要はなくif(cond)
、許可するという追加の使用法があります
if (cond && maybeFunc())
;// Code here I want to ignore
これを許可するのは実際にはひどい考えですが。これを確認するために、許可してからケースを追加する方が簡単です。
Javaは、ステートメントブロックが許可されている場所であればどこでも空のブロックを許可します。これをすべてのブロックの一般的なルールにすることで、コンパイラーが単純化されると確信しています。
これが主に、見事に見つけるのが難しいバグの原因であることに同意します。ステートメントが1つしかない場合でも、常にブロックを中かっこで囲みますが、Javaではいつでも中かっこでブロックを作成できるため、中かっこを使用してもこの運命から救うことはできません。たとえば、私はかつて次のようなものを見つけようとして4時間を無駄にしました。
while (condition);
{
statement;
statement;
}
最初の行の終わりにあるセミコロンはタイプミスであり、誤ってwhileループのステートメントブロックを空にしました。構文は有効であるため、プログラムはコンパイルされて正常に実行されましたが、私が望んでいた方法ではありませんでした。見つけるのは本当に大変でした。
空のブロックを使用できるのは非常に便利な状況の1つと考えることができます。これは、次のようなものです。
if (condition1) {
do_action_1();
}
else if (condition2) {
//nothing really to do in this case
}
else if (condition3) {
do_action2();
}
else {
do_action3();
}
上記の例では、さまざまな条件を分離できるようにする必要があります。これらの条件が重複している可能性があるため、順序を並べ替えることが常に可能であるとは限らないことに注意してください。条件の1つで実際に何もする必要がない場合は、Javaで空のブロックを使用できるのは便利です。そうしないと、本当に何もしたくないときに使用するために、言語に何らかの形の「noop」メソッドが必要になります。
私は個人的に明示的な「noop」ステートメントを好みますが、それはJavaの定義方法ではありません。
使いやすさと、そのような声明がある場合にどのような違いが生じるか、または生じる可能性があるかについての参考までに
次のようなコードを考えてみましょう。
int a = 10;
if ((a = 50) == 50);
System.out.println("Value of a = " + a);
この場合明らかに、if
ステートメントは出力を変更します。したがって、そのような声明は違いを生む可能性があります。
これは、これが有用である、またはプログラムに影響を与えると言ったほうがよい状況です。
if(a==b)
println("a equals b");
{}
実行する行が1行しかない場合は、IFステートメントを使用できif(a==b);
ます。したがって、それらが等しいかどうかを使用すると、ステートメントを実行して空にします...したがって、何も実行されず、通常のループに戻ります。 IFブロックの。
jls からのいくつかの定義がこれを説明しています (第 14 章)。
ここで述べたように、aBlock
は aStatementWithoutTrailingSubstatement
であり、 aStatementNoShortIf
は aStatement
です。したがって、これらのいずれかが必要な場合はいつでも、Block
.
これは forfor
とwhile
-loops にも当てはまりますが、ここではif
-statements を使用します。これらのルールはほとんど同じです。の構文説明は、ここif-statements
にあります。
IfThenStatement:
if ( Expression ) Statement
IfThenElseStatement:
if ( Expression ) StatementNoShortIf else Statement
IfThenElseStatementNoShortIf:
if ( Expression ) StatementNoShortIf else StatementNoShortIf
したがって、ここでブロックを使用できます。
;
はEmptyStatement
(リンク) として定義されており、これもStatementNoShortIf
です。そのため、 や ループなどの条件付きコードでは、 orが必要な場合はaを aにif-statement
置き換えることができます。Block
EmptyStatement
StatementNoShortIf
Statement
したがって、if(Expression)EmptyStatement
動作します。
非常に単純です。無効な構文が見つかった場合、java はエラーを返します。しかしif(Expression)EmptyStatement
、完全に有効な構文です。代わりjavac
に、適切なパラメーターで起動すると警告が表示されます。無効化/有効化できる警告の完全なリストにはempty
、この目的のための警告名がリストされています。-Xlint:all
したがって、 orを使用してコンパイルすると-Xlint:empty
、これに関する警告が生成されます。
IDE には、この種の警告も有効にするオプションが必要です。Eclipse については、@nullptr の回答を参照してください。IntelliJ では、 を押して検索フィールドCtrl + Shift + A
に入力し、警告を有効にすることができます (画像にマークされています)。empty body
正直なところ、ミニマルな観点からはあまり役に立ちません。通常、「何もしない」コマンドなしで物事を成し遂げる方法があります。どちらを使用するかは個人の好みの問題です。
if( a() && b() );
また
if( a() ) b();
が使用される他の場合にも同じことが当てはまりますEmptyStatement
。このトピックで考慮すべき重要な点は、コードの読みやすさです。no-op を使用することでコードが読みやすくなる場合があります。一方、 を使用するとコードが非常に理解しにくくなる場合がありますEmptyStatement
。上記の例は後の IMO にカウントされます。
空のステートメントが必要なシナリオを考えることができます (forif
条件ではなく forwhile
ループ)。
プログラムが続行するためにユーザーからの明示的な確認のみを必要とする場合。これは、ユーザーの確認後の作業が他のものに依存し、ユーザーがいつ続行するかを制御したい場合に必要になることがあります。
System.out.println("Enter Y to proceed. Waiting...");
System.out.println("");
while(!(new Scanner(System.in).next().equalsIgnoreCase("Y")));
System.out.println("Proceeding...");
// do the work here
if(a==b);の最後にセミコロン つまり、条件の結果を無視して次の行から実行を継続するということ
です。このコードは便利ですが、一方でプログラムにバグを導入することもあります。たとえば、
ケース 1.
a = 5;
b = 3;
場合 (a == b);
prinf("a と b は等しい");
ケース 2。
a = 5;
b = 5;
場合 (a == b);
prinf("a と b は等しい");
画面に同じ出力を印刷します...