Java Language Pitfall - Quitter les accolades: les problèmes de "pendants si" et de "pendants"


Exemple

La dernière version du guide de style Java Oracle exige que les instructions "then" et "else" d'une instruction if soient toujours placées entre "accolades" ou "accolades". Des règles similaires s'appliquent aux corps des différentes instructions de boucle.

if (a) {           // <- open brace
    doSomething();
    doSomeMore();
}                  // <- close brace

Ce n'est pas réellement requis par la syntaxe du langage Java. En effet, si la partie "alors" d’une déclaration if est une déclaration unique, il est légal de laisser de côté les accolades

if (a)
    doSomething();

ou même

if (a) doSomething();

Cependant, il y a des dangers à ignorer les règles de style Java et à laisser de côté les accolades. Plus précisément, vous augmentez considérablement le risque que le code avec une indentation erronée soit mal interprété.

Le problème du "dangling if":

Considérez l'exemple de code ci-dessus, réécrit sans accolades.

if (a)
   doSomething();
   doSomeMore();

Ce code semble dire que les appels à doSomething et doSomeMore se produiront tous les deux si et seulement si a est true . En fait, le code est indenté incorrectement. La spécification de langage Java que l'appel doSomeMore() est une instruction distincte suivant l'instruction if . L'indentation correcte est la suivante:

if (a)
   doSomething();
doSomeMore();

Le problème du "dangling else"

Un deuxième problème apparaît lorsque l' on ajoute le else au mélange. Prenons l'exemple suivant avec des accolades manquantes.

if (a)
   if (b)
      doX();
   else if (c)
      doY(); 
else
   doZ();

Le code ci-dessus semble dire que doZ sera appelé quand a est false . En fait, l'indentation est incorrecte encore une fois. L'indentation correcte du code est la suivante:

if (a)
   if (b)
      doX();
   else if (c)
      doY(); 
   else
      doZ();

Si le code était écrit conformément aux règles de style Java, cela ressemblerait à ceci:

if (a) {
   if (b) {
      doX();
   } else if (c) {
      doY(); 
   } else {
      doZ();
   }
}

Pour illustrer pourquoi cela est mieux, supposez que vous ayez accidentellement induit le code en erreur. Vous pourriez vous retrouver avec quelque chose comme ça:

if (a) {                         if (a) {
   if (b) {                          if (b) {
      doX();                            doX();
   } else if (c) {                   } else if (c) {
      doY();                            doY();
} else {                         } else {
   doZ();                            doZ();
}                                    }
}                                }

Mais dans les deux cas, le code mal indenté "semble erroné" aux yeux d'un programmeur Java expérimenté.