web-dev-qa-db-ja.com

空のifステートメント

「空のifステートメント」とは、次のような意味です(セミコロンに注意してください)。

if (condition);

私はこのためのアプリケーションを考えるのに苦労しています。 whileループを使用すると、次のことができます。

while (callUntilReturnsFalse());

しかし、if文にはそのようなアプリケーションはありません。さらに、Javaコンパイラーは、このようなステートメントに直面したときにエラーや警告を発行しません。これにより、大きなsilent問題、特に長く複雑なステートメントに関する問題:

if ((functionA() && functionB(getFoo()) ||
    checkForComplexCondition(arg1, arg2, getBar(getFoo())));
{
    doStuff();
}

私の質問は、なぜこれがJavaで許可されているのかということです。さらに重要なことは、これが発生したときに警告を出すオプションを有効にできますか?

(この質問は 以前に尋ねた 警告を発行するC#に関してでしたが、Javaで警告を引き起こす方法を見つけたいと思っていました。)

23
nullptr

なぜこれがJavaで許可されているのですか?

Java言語仕様(14.6。空のステートメント) を参照してください:

空のステートメントは何もしません。

それは単に許可されており、同等です(そして翻訳されます):

if (condition) {  }

つまり、条件が真の場合、何もしません。

Eclipseを使用している場合は、こちらを参照してください。何か便利なものが見つかるかもしれません(セミコロンターミネータのようなオプションが存在するかどうかはわかりません)。

WindowPreferencesJava コンパイラエラー/警告

enter image description here


編集

@nullptrが彼の答えで指摘したように、IDEこれに対する警告が存在します。あなたはwarningを設定する必要があります空のステートメント

14
Maroun

私はこれが質問の意図に真に関連するとは思わないが、質問の本質に関連しているのでそれを述べるべきだと思う。

そこにはisの効果があります:

if(variable);

変数がvolatileの場合。その効果は、現在のスレッドと変数にアクセスする他のスレッドとの間でメモリバリアが尊重されるようにすることです。

public volatile variable;
....
if(variable);

より詳細な議論については here をご覧ください。

この種のステートメントをコードに入れることの本当の価値は想像できませんが、この非常に特殊な状況では、このステートメントに実際の効果があることに注意することが重要だと感じました。

13
OldCurmudgeon

私がかなり頻繁に使用する構成要素が1つあります。これは、「nullステートメント」によってより明確で理解しやすくなります。以下に例を示します。

for (int i=0;  i < argc;  i++)
{
   if (argv[i]=="left")
      hpos++;
   else if (argv[i]=="right")
      hpos--;
   else if (argv[i]=="up")
      ;
   else if (arv[i]=="down")
      ;
   else fprintf(stderr, "Unknown option \"%s\\n".", argv[i]);
}

この場合、私はまだ確認したい 存在 特定のオプションのうち、 一部 そのうちの。この場合、上記のようにnullステートメントを使用すると、コードの機能と構造が読みやすく、理解しやすい次の人にわかりやすくなります。

Nullステートメントを必要としないようにこのコードを再構築する方法は確かにあります。しかし、その意図がコードスニペットのように明確になるとは思わない。

4
Curt

EclipseでEmpty statementとしてこれに関する警告を見つけました:

example

私を正しい方向に導いてくれたMaroun Marounに感謝します。

2
nullptr

空のステートメントを持つifの可能性にはそれほど危険はないと思います。その背後にある理論的根拠は、Java言語の文法にあり、空の文;

Block: 
    { BlockStatements }

BlockStatements: 
    { BlockStatement }

BlockStatement:
    LocalVariableDeclarationStatement
    ClassOrInterfaceDeclaration
    [Identifier :] Statement

LocalVariableDeclarationStatement:
    { VariableModifier }  Type VariableDeclarators ;

Statement:
    Block
    ;
    Identifier : Statement
    StatementExpression ;
    if ParExpression Statement [else Statement] 
    assert Expression [: Expression] ;
    switch ParExpression { SwitchBlockStatementGroups } 
    while ParExpression Statement
    do Statement while ParExpression ;
    for ( ForControl ) Statement
    break [Identifier] ;
    continue [Identifier] ;
    return [Expression] ;
    throw Expression ;
    synchronized ParExpression Block
    try Block (Catches | [Catches] Finally)
    try ResourceSpecification Block [Catches] [Finally]

これはほとんどすべての命令型言語に当てはまることに注意してください。

実装を忘れた場合、他のすべての空のボディとして見つけるのは危険で困難になる可能性がありますが、確かに私は睡眠を失うことはありません。長く複雑な文では、( )間違った表現のペアを閉じたり、条件を間違っていると考えるために(特に多くの&&および||)。

2
Jack

条件は、副作用を伴う関数呼び出しである可能性があります。エラーまたは警告として扱うのは正しくありません。

1
user207421

私は主にC#開発者ですが、少しのJavaバックグラウンドがあります。しかし、私の答えは両方に当てはまると思います。言語の文法が(大体)行く

if (*condition*)
    *statement*

残念ながら、以下は両方とも有効なステートメントです(チェックしましたが、好きなだけC#にドロップでき、コンパイラーは文句を言いません):

;

{
}

したがって、強調表示した構造は許可されます。

1
David Cummins

コードを読みやすくするために残しておいたと思います。ケースに対して何もすべきでない場合でも、そのケースが重要であることを人々に知らせたい場合があります。

0
aaronman

ほとんどのJavaコンパイラーはコードの最適化をまったく行いません。ランタイム中にこの作業をJava Runtime Environment。JVMは実行前にコードを検証し、 butこの検証は、(主に)3つのチェックで構成されます。

  1. 有効位置(正しいと同じではない)の分岐。
  2. データは常に初期化され、参照は常にタイプセーフです
  3. プライベートデータへのアクセスは制御されます。

したがって、ifステートメントはwrongかもしれませんが、それでも有効です。として有効

 if (a==a)
0
aran

声明で

if  (eval) { //pseudo-code
}

(eval)の評価で実際にデータが変更される場合があります。たとえば、

while (someIterator.next()) {
}

Next()を呼び出すと、実際にsomeIteratorオブジェクトの状態が変更されます。

そしてもちろん、通常タイプミスから生じる典型的な例があります(推奨されません)

int x;  
if (x = getNumberOfWidgets() > 5) {
}

何が起こっているのかわかりにくいため、従来の知恵ではこの方法でコーディングすることはお勧めしません。ただし、ステートメントは合法であるため、そのような「if」ステートメントが許可される理由の1つです。

0
user1445967