Point-virgule à la fin de l'if

aujourd'Hui, après une demi-heure de recherche pour un bug, j'ai découvert qu'il est possible de mettre un point-virgule après l'instruction if au lieu de code, comme ceci:

if(a == b);
// Do stuff

ce qui signifie essentiellement que le truc sera fait que a égale b ou non, et la déclaration de si n'a aucun sens. Pourquoi Java ne me donne-t-il pas une erreur? Est-il une situation où ce serait utile?

61
demandé sur Peter Mortensen 2013-01-01 21:22:12

16 réponses

pourquoi ça arrive?

Java Language Specification says that:

L'Instruction Vide

une déclaration vide ne fait rien.

EmptyStatement:
    ;

L'exécution d'une instruction vide se termine toujours normalement

cela signifie essentiellement que vous voulez exécuter l'instruction vide si a = = b

if(a == b);

Que devez-vous faire:

il y a deux principales solutions à ce problème:

  1. vous pouvez éviter les problèmes avec la déclaration vide en utilisant le Code formatter et tout ce qui l'entoure à l'intérieur de if avec { et } . En faisant cela, Votre déclaration vide sera beaucoup plus lisible.

    if(a == b){
      ;
    }
    
  2. Vous pouvez également vérifier outils utilisés pour l'analyse de codes statiques tels que:

    ils peuvent instantanément mettre en évidence des problèmes tels que celui-ci.

je recommande de combiner les deux solution.

82
répondu Marcin Szymczak 2013-06-04 10:02:23

y a-t-il une situation dans laquelle cela serait utile?

utile? Comme dans "rend votre code plus propre, plus clair, plus rapide, plus maintenable"? Pas du tout. C'est très probablement code pauvre et confus .

mais ce n'est pas nécessairement Bénin . Une telle déclaration peut effectuer des actions et / ou modifier l'état en raison de méthodes qui causent des effets secondaires, et évaluer ceux-ci méthodes dues à court-circuitage des opérateurs .

if( a() && b() );

Ici, a() ou b() peut faire quelque chose, et b() ne s'exécutera que si a() est vrai.

quant à pourquoi , je pense que la réponse est simplement qu'il serait pire de s'écarter du comportement défini et attendu (par exemple des déclarations comme while(reader.read()); ) que l'alternative des développeurs écrivant du mauvais code.

Écrire un mauvais code est toujours possible. Et juste pour le répéter, ce serait un mauvais code dans presque tous les cas.

27
répondu Tim Medora 2013-01-02 16:07:06

un cas d'utilisation possible:

if (a==b);
else {
  // Do something
}

pas bon, mais possible.

pourtant, je pense que la spécification Java devrait rejeter un vide if .

19
répondu gefei 2016-02-28 02:45:11

si vous utilisez Eclipse, vous pouvez le faire vous avertir à propos de ces déclarations:

Java-Compiler-Errors/Warnings

10
répondu nullptr 2013-05-07 22:09:53

si vous utilisez une instruction if , la première instruction après la if sera exécutée si la condition est vraie. Si vous avez un bloc après le if (avec attelles bouclées), il compte pour tout le bloc. Si il n'y a pas de bloc il compte pour une seule instruction. Un seul point-virgule est une instruction vide. Vous pouvez aussi écrire le code de votre exemple comme ceci:

if(a==b) {
    ;
}
7
répondu André Stannek 2013-01-01 17:27:15

c'est un vieux résidu de l'époque où il y avait plus de sucre syntaxique pour différencier les expressions des affirmations.

essentiellement, la virgule a été utilisée comme séparateur d'éléments de liste, de sorte que le point-virgule a été utilisé comme séparateur de" liste d'énoncés". L'inconvénient est dans le traitement des éléments nuls dans les listes, et les déclarations nulles dans les blocs.

dans une liste D'articles, Java utilise le mot-clé explicite null , mais une "déclaration nulle" est juste un ligne vide. Permettre l'existence d'une ligne vide est un prolongement de la tradition héritée de C.

Pourquoi faire? En particulier avec une déclaration if quand vous savez qu'Aucune déclaration n'est exécutée: parce que certains si les déclarations ont des effets secondaires:

 int c;
 if ((c = in.read()) != -1);

Oui, ce n'est pas le meilleur exemple, mais fondamentalement il dit lire un octet du ruisseau et ne rien faire. Peut être utile dans certains cas particuliers, mais même si cet exemple n'est pas le mieux, il illustre l'intention. Nous voulons ressentir les effets secondaires de l'expression sans exécuter accidentellement des déclarations.

6
répondu Edwin Buck 2013-01-01 22:13:40

je ne peux pas penser à une occasion où il est utile. Il peut être utile pour les boucles comme

 while(do something);

ou

 for(init; do something; something else);

si vous utilisez votre formatage de code dans votre IDE régulièrement ces sortes de bogues deviennent évidents. Certains IDEs soulignent également qu'il s'agit d'un bogue probable.

5
répondu Peter Lawrey 2013-01-01 17:25:25

je serai d'accord avec vous il n'y a aucune utilité pour l'homme. Je soupçonne qu'il est là parce qu'il simplifie la définition de la langue; il signifie que la chose qui vient après un if est e même que la chose qui vient après un while , par exemple.

4
répondu yshavit 2013-01-01 17:27:41

pourquoi? C'est parce que c'est plus facile pour les rédacteurs de compilateurs. Vous ne devez pas faire un cas spécial pour vérifier les points-virgule après if(cond) et a une utilisation supplémentaire d'autoriser

if (cond && maybeFunc())
    ;// Code here I want to ignore

même si c'est une très mauvaise idée de permettre cela. Il est juste plus facile d'autoriser et puis d'ajouter un cas pour vérifier cela.

3
répondu Peter Mortensen 2016-02-28 02:51:02

Java permet un bloc vide n'importe où un bloc de déclaration est autorisé. Je suis sûr que faire de cela une règle générale pour tous les blocs simplifie le compilateur.

je suis d'accord que c'est principalement la cause des bogues qui sont extraordinairement difficiles à trouver. J'utilise toujours des bagues autour des blocs, même lorsqu'il n'y a qu'une seule déclaration, mais Java vous permet de faire un bloc avec des bagues à tout moment, donc utiliser des bagues ne peut pas vous sauver de ce destin. Par exemple, j'ai perdu une fois 4 heures essayer de trouver quelque chose comme ceci:

while (condition);
{
    statement;
    statement;
}

le point-virgule à la fin de la première ligne était une faute de frappe, rendant accidentellement vide le bloc d'instructions pour la boucle while. Parce que la syntaxe est valide, le programme a été compilé et s'est bien déroulé, mais pas comme je le voulais. C'était vraiment difficile à trouver.

je ne peux penser à une situation où il est très gentil que vous êtes autorisé à avoir des blocs vides, et c'est quelque chose comme ceci:

if (condition1) {
    do_action_1();
}
else if (condition2) {
    //nothing really to do in this case
}
else if (condition3) {
    do_action2();
}
else {
    do_action3();
}

dans l'exemple ci-dessus, vous voulez pouvoir séparer diverses conditions. Rappelez-vous, ces conditions peuvent être superposées, de sorte qu'il n'est pas toujours possible de réorganiser l'ordre. Si l'une des conditions n'a pas vraiment besoin de rien faire, alors c'est bien que Java permet d'avoir un bloc vide. Sinon, le langage aurait besoin d'une certaine forme de méthode "noop" à utiliser quand vous ne voulez vraiment pas que quelque chose soit fait.

personnellement, je préférerais l'énoncé explicite "noop" -- mais ce N'est pas ainsi que Java est défini.

2
répondu AgilePro 2013-01-01 23:02:28

Juste pour info au sujet de la convivialité et de la la différence qu'il fait ou peut faire si il ya une telle déclaration

considérez un morceau de code comme le suivant.

int a = 10;
if ((a = 50) == 50);

System.out.println("Value of a = " + a);

clairement dans ce cas, l'énoncé if change la sortie. Une telle déclaration peut donc faire une différence.

C'est une situation où cela pourrait être utile, ou pour mieux dire avoir un impact sur le programme.

2
répondu Mukul Goel 2016-02-28 03:00:45
if(a==b)
    println("a equals b");

vous pouvez utiliser une instruction IF sans {} s'il n'y a qu'une seule ligne à exécuter, donc en utilisant if(a==b); vous dites si elles sont égales, exécutez et videz l'instruction... Donc, il ne fera rien, et ensuite revenir à votre boucle normale, en dehors du bloc si.

1
répondu Matt Clark 2013-01-01 18:20:30

quelques définitions du jls expliquent ceci (chapitre 14):

Blocs sont des Énoncés

comme indiqué ici , un Block est un StatementWithoutTrailingSubstatement , qui à son tour est un StatementNoShortIf , qui est un Statement . Ainsi, lorsque l'un quelconque de ces éléments est requis, nous pouvons insérer un Block .

si la clause

bien que ce soit aussi le cas pour for et while - loops, je vais utiliser if - statements. Ces règles sont à peu près les mêmes. La description syntaxique de if-statements peut être trouvée ici .

IfThenStatement:
    if ( Expression ) Statement

IfThenElseStatement:
    if ( Expression ) StatementNoShortIf else Statement

IfThenElseStatementNoShortIf:
    if ( Expression ) StatementNoShortIf else StatementNoShortIf

donc nous pouvons utiliser notre bloc ici.

mais pourquoi cela fonctionne-t-il avec ; ?

; est défini comme le EmptyStatement ( link ), qui est aussi un StatementNoShortIf . Ainsi en morceaux conditionnels de code, comme if-statement et les boucles, nous pouvons remplacer un Block par un EmptyStatement , si un StatementNoShortIf ou Statement est nécessaire.

donc if(Expression)EmptyStatement travaux.

pourquoi ça ne donne pas une erreur?

assez simple: java donne une erreur si elle trouve une syntaxe invalide. Mais if(Expression)EmptyStatement est une syntaxe parfaitement valide. Au lieu de cela javac donne un avertissement si lancé avec les paramètres appropriés. Le complet liste des avertissements qui peuvent être désactivés/activés liste l'avertissement-nom empty à cette fin. Ainsi la compilation avec -Xlint:all ou -Xlint:empty générera un avertissement à ce sujet.

votre IDE devrait aussi avoir une option pour activer ce type d'avertissement. Pour eclipse, voir la réponse de @nullptr . Dans IntelliJ, vous pouvez appuyer sur Ctrl + Shift + A , entrer empty body dans le champ de recherche et activer l'avertissement (marqué dans l'image)

IntelliJ enable empty-body warning

à quoi sert-il?

pour être honnête, il n'y a pas beaucoup d'utilisation d'un point de vue minimaliste. Il y a généralement un moyen de faire les choses sans un ordre de "ne rien faire". C'est plutôt une question de préférences personnelles, si vous utilisez plutôt

if( a() && b() );

ou

if( a() ) b();

et même s'appliquer à d'autres cas, dans lesquels le EmptyStatement est utilisé. Un point important à considérer sur ce sujet est la lisibilité du code. Il y a des occasions, où le code devient plus lisible en utilisant le no-op. D'un autre côté, il y a des cas où le code devient beaucoup plus difficile à comprendre avec l'utilisation du EmptyStatement - l'exemple ci-dessus compterait pour L'IMO plus tard.

1
répondu Paul 2017-05-23 12:26:25

Point-Virgule à la fin de

if (a==b); simplement terminer l'instruction en une seule ligne, ce qui signifie ignorer le résultat de la condition et continuer l'exécution à partir de la ligne suivante

Ce code est utile, d'autre part, parfois, introduire un bug dans le programme, par exemple,



cas 1.



a = 5;

b = 3;

si (a == b);

prinf("a et b sont égaux");



cas 2.



a = 5;

b = 5;

si (a == b);

prinf ("a et b sont égaux");

imprimez le même résultat sur l'écran...

0
répondu Narayan Bhandari 2013-01-01 23:40:36

je peux penser à un scénario où un énoncé vide est requis (pas pour la condition if mais pour la boucle while ).

quand un programme veut juste une confirmation explicite de l'utilisateur pour procéder. Cela peut être nécessaire lorsque le travail après la confirmation de l'utilisateur dépend d'autres choses et de l'utilisateur veut prendre le contrôle de quand à poursuivre.

    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
0
répondu Parvez 2013-01-02 08:31:42

en travaillant sur une tâche de programmation pour class où je travaille avec une grille n by N de doodads et en comparant les caractéristiques d'un doodad aléatoire à celles ci-dessus, en bas, à gauche et à droite, j'ai trouvé une bonne utilisation de ceci pour prévenir des déclarations emboîtées et des exceptions de limite potentielles. Mon but était de minimiser le code et d'éviter de faire des déclarations if.

if (row == 0); 
else (method (grid[row][col], grid[row-1][col]));
if (row == N-1);
else (method (grid[row][col], grid[row+1][col]));
if (col == 0);
else (method (grid[row][col], grid[row][col-1]));
if (col == N-1);<br>
else (method (grid[row][col], grid[row][col+1]));

method(Doodad a, Doodad b) fait une certaine opération entre a et B.

Alternativement, vous pouvez utiliser la manipulation d'exception pour éviter cette syntaxe, mais elle fonctionne et fonctionne bien pour mon application.

-2
répondu George C 2017-09-24 12:37:15