it-swarm.com.de

Leere if-Anweisungen

Mit "leere if-Anweisung" meine ich so etwas (beachte das Semikolon):

if (condition);

Ich habe Probleme, an eine Anwendung dafür zu denken. Mit einer while-Schleife können Sie Folgendes tun:

while (callUntilReturnsFalse());

Es gibt jedoch keine solche Anwendung für eine if-Anweisung. Darüber hinaus gibt der Java-Compiler keinen Fehler oder eine Warnung aus, wenn er mit einer solchen Anweisung konfrontiert wird. Dies kann zu großen und silent - Problemen führen, insbesondere bei einer langen und verschachtelten Anweisung:

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

Meine Frage ist: Warum ist das in Java erlaubt? Und was noch wichtiger ist: Kann ich eine Option aktivieren, um in diesem Fall eine Warnung auszulösen?

(Diese Frage wurde zuvor gestellt in Bezug auf C #, das eine Warnung ausgibt, aber ich hoffte, einen Weg zu finden, eine Warnung mit Java auszulösen.)

23
nullptr

Warum ist das in Java erlaubt?

Siehe Java-Sprachspezifikation (14.6. Die leere Anweisung) :

Eine leere Aussage macht nichts.

Es ist einfach erlaubt und es entspricht (und wird übersetzt):

if (condition) {  }

Was bedeutet, wenn die Bedingung wahr ist, nichts tun.

Wenn Sie Eclipse verwenden, können Sie hier nachsehen. Vielleicht finden Sie etwas Nützliches (Ich bin nicht sicher, ob es eine solche Option für das Semikolon-Terminator gibt):

WindowPreferencesJavaCompilerFehler/Warnungen

enter image description here


BEARBEITEN

Wie @nullptr in seiner Antwort darauf hinweist, gibt es dafür eine IDE Warnung. Sie müssen warning auf Empty-Anweisung setzen.

14
Maroun

Ich glaube nicht, dass dies für die Intention der Frage wirklich relevant ist, aber ich denke, es sollte angegeben werden, da es für das Wesentliche der Frage relevant ist.

Is ein Effekt eines:

if(variable);

wenn die Variable volatile ist. Dies bewirkt, dass eine Speicherbarriere zwischen dem aktuellen Thread und allen anderen Threads, die auf die Variable zugreifen, berücksichtigt wird.

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

Siehe hier für eine ausführlichere Diskussion.

Ich kann mir keinen wirklichen Wert vorstellen, diese Art von Aussage in Ihren Code aufzunehmen, aber es war mir wichtig zu bemerken, dass diese Aussage in dieser sehr spezifischen Situation einen wirklichen Effekt hat.

13
OldCurmudgeon

Es gibt ein Konstrukt, das ich ziemlich häufig verwende, das die "Null-Anweisung" klarer und verständlicher macht. Hier ist ein Beispiel:

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]);
}

In diesem Fall möchte ich noch nach dem suchen existenz bestimmter Optionen, während nur Code für ausgeführt wird etwas von ihnen. In diesem Fall macht die Verwendung der null-Anweisung, wie oben beschrieben, die Funktion und Struktur des Codes für den nächsten Benutzer, der mitkommen und ihn warten muss, lesbarer und verständlicher. 

Es gibt sicherlich Möglichkeiten, diesen Code so umzustrukturieren, dass die Null-Anweisung nicht erforderlich ist. Aber ich glaube nicht, dass seine Absicht so klar sein wird wie im Code-Snippet.

4
Curt

Ich habe in Eclipse eine Warnung als Empty statement gefunden:

example

Danke an Maroun Maroun, der mich auf die richtige Spur gebracht hat.

2
nullptr

Ich sehe in der Möglichkeit einer if mit einer leeren Aussage nicht so viel Gefahr. Der Grund dafür liegt in der Grammatik der Java-Sprache, die die leere Anweisung ; erlaubt:

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]

Beachten Sie, dass dies für fast alle imperativen Sprachen gilt.

Ich meine, es kann gefährlich und schwierig sein, wie alle anderen leeren Körper zu finden, falls Sie eine Implementierung vergessen haben, sicherlich nichts, für das ich den Schlaf verlieren würde. In einer langen und verschachtelten Anweisung könnten Probleme auftreten, weil ein ( ) das falsche Paar von Ausdrücken schließt oder sogar, dass Ihre Bedingung falsch ist (insbesondere bei vielen && und ||).

2
Jack

Die Bedingung könnte ein Funktionsaufruf mit Nebenwirkungen sein. Es wäre nicht richtig, es als Fehler oder Warnung zu behandeln.

1
user207421

Ich bin hauptsächlich ein C # -Entwickler, obwohl ich ein wenig Java-Hintergrund habe. Aber ich denke, meine Antwort trifft auf beide zu. Ich vermute, es ist keine absichtliche Funktion, sondern eher eine aufkommende Funktion. Die Grammatik der Sprache geht (ungefähr)

if (*condition*)
    *statement*

Leider sind im Folgenden beide gültige Anweisungen (ich habe geprüft, Sie können beliebig viele in C # ablegen und der Compiler beschwert sich nicht):

;

{
}

Daher ist das von Ihnen hervorgehobene Konstrukt zulässig.

1
David Cummins

Ich glaube, dass sie es gelassen haben, weil es die Lesbarkeit des Codes verbessern kann. Selbst wenn für einen Fall nichts unternommen werden soll, möchten Sie vielleicht trotzdem die Leute wissen lassen, dass der Fall wichtig ist. 

0
aaronman

Die meisten Java-Compiler führen keine Optimierung des Codes durch. Sie delegieren diese Arbeit während der Laufzeit an die Java-Laufzeitumgebung. Die JVM überprüft den Code, bevor er ausgeführt wird,, aber diese Überprüfung besteht (hauptsächlich) aus drei Prüfungen:

  1. Verzweigungen in gültige Positionen (nicht dasselbe wie richtige).
  2. Daten werden immer initialisiert und Referenzen sind immer typsicher
  3. Der Zugriff auf private Daten wird kontrolliert.

Ihre if-Anweisung kann also false sein, ist aber dennoch gültig. So gültig wie

 if (a==a)
0
Asier Aranbarri

In der Aussage

if  (eval) { //pseudo-code
}

Manchmal werden Daten bei der Auswertung von (eval) tatsächlich geändert. Zum Beispiel in

while (someIterator.next()) {
}

Durch Aufrufen von next () wird tatsächlich der Status des someIterator-Objekts geändert.

Und natürlich gibt es das klassische Beispiel, das normalerweise bei einem Tippfehler auftritt (und nicht empfohlen wird).

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

Konventionelle Weisheit rät davon ab, auf diese Weise zu codieren, da es schwieriger ist, zu erkennen, was los ist. Die Aussagen sind jedoch legal, und das ist ein Grund, warum eine solche "if" -Anweisung zulässig ist. 

0
user1445967