91 votes

L'utilisation d'une pause étiquetée est-elle une bonne pratique en Java ?

Je regarde un vieux code datant de 2001 et je suis tombé sur cette déclaration :

   else {
     do {
       int c = XMLDocumentFragmentScannerImpl.this.scanContent();
       if (c == 60) {
         XMLDocumentFragmentScannerImpl.this.fEntityScanner.scanChar();
         XMLDocumentFragmentScannerImpl.this.setScannerState(1);
         break label913;
       }

Je n'avais jamais vu ça avant, et j'ai découvert des pauses étiquetées ici :

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/branch.html

Cela ne fonctionne-t-il pas essentiellement comme goto ? Est-ce même une bonne pratique de l'utiliser ? Cela me met mal à l'aise.

131voto

Thomas Points 35713

Non, ce n'est pas comme un goto, puisque vous ne pouvez pas "aller" à une autre partie du flux de contrôle.

De la page que vous avez liée :

L'instruction break met fin à l'instruction étiquetée ; elle ne transfère pas le flux de contrôle à l'étiquette. Le flux de contrôle est transféré à l'instruction qui suit immédiatement l'instruction étiquetée (terminée).

Cela signifie que vous ne pouvez interrompre que les boucles qui sont en cours d'exécution.

Prenons cet exemple :

first:
for( int i = 0; i < 10; i++) {
  second:
  for(int j = 0; j < 5; j ++ )
  {
    break xxx;
  }
}

third:
for( int a = 0; a < 10; a++) {

}

Vous pourriez remplacer xxx avec first ou second (pour interrompre la boucle extérieure ou intérieure), puisque les deux boucles sont en cours d'exécution, lorsque vous appuyez sur la touche break mais en remplaçant xxx avec third ne compilera pas.

17voto

Nathan Hughes Points 30377

Ce n'est pas aussi terrible que goto car il n'envoie le contrôle qu'à la fin de l'instruction étiquetée (généralement une construction en boucle). Ce qui rend goto Ce qui est différent, c'est qu'il s'agit d'une branche arbitraire vers n'importe quel endroit, y compris des étiquettes trouvées plus haut dans le source de la méthode, de sorte que vous pouvez avoir un comportement de bouclage fait maison. La fonctionnalité de rupture d'étiquette en Java ne permet pas ce genre de folie car le contrôle ne va qu'en avant.

Je ne l'ai utilisé qu'une seule fois il y a environ 12 ans, dans une situation où j'avais besoin de sortir de boucles imbriquées, l'alternative plus structurée aurait rendu les tests plus compliqués dans les boucles. Je ne conseillerais pas de l'utiliser souvent, mais je ne le considérerais pas comme un mauvais code automatique.

11voto

logicray Points 311

Il est toujours possible de remplacer break avec une nouvelle méthode.

Considérons le code vérifiant la présence d'éléments communs dans deux listes :

List list1, list2;

boolean foundCommonElement = false;
for (Object el : list1) {
    if (list2.contains(el)) {
        foundCommonElement = true;
        break;
    }
}

Vous pouvez le réécrire comme ceci :

boolean haveCommonElement(List list1, List list2) {
    for (Object el : list1) {
        if (list2.contains(el)) {
            return true;
        }
    }
    return false;
}

Bien sûr, pour vérifier les éléments communs entre deux listes, il est préférable d'utiliser list1.retainAll(new HashSet<>(list2)) pour le faire à O(n) avec O(n) mémoire supplémentaire, ou trier les deux listes à O(n * log n) et ensuite trouver des éléments communs à O(n) .

8voto

parsifal Points 241

Avant de lire le reste de cette réponse, veuillez lire les points suivants Aller à la déclaration considérée comme nuisible . Si vous ne voulez pas le lire en entier, voici ce que je considère comme le point clé :

L'utilisation débridée de la déclaration de destination a pour conséquence immédiate qu'il devient terriblement difficile de trouver un ensemble de coordonnées significatives pour décrire l'évolution du processus.

Ou pour reformuler, le problème avec goto est que le programme peut arriver au milieu d'un bloc de code, sans que le programmeur comprenne l'état du programme à ce moment-là. Les constructions standard orientées blocs sont conçues pour délimiter clairement les transitions d'état, un bloc étiqueté break est destiné à amener le programme à un état spécifique connu (en dehors du bloc étiqueté contenant).

Dans un programme impératif réel, l'état n'est pas clairement délimité par les frontières des blocs, de sorte qu'il est possible de se demander si l'étiquette break est une bonne idée. Si le bloc change d'état de manière visible depuis l'extérieur du bloc et qu'il existe plusieurs points de sortie du bloc, alors une étiquette de type break est équivalent à la primitive goto . La seule différence est que, au lieu d'avoir la chance d'atterrir au milieu d'un bloc à état indéterminé, vous commencez un nouveau bloc à état indéterminé.

Donc, en général, je considérerais qu'une étiquette break comme dangereux. À mon avis, c'est un signe que le bloc doit être converti en une fonction, avec un accès limité à la portée englobante.

Cependant, cet exemple de code était clairement le produit d'un générateur d'analyseur (le PO a commenté qu'il s'agissait du code source de Xerces). Et les générateurs d'analyseurs (ou les générateurs de code en général) prennent souvent des libertés avec le code qu'ils génèrent, car ils ont une connaissance parfaite de l'état et les humains n'ont pas besoin de le comprendre.

2voto

Marek Points 510

Une manière plus propre d'exprimer l'intention pourrait être, du moins à mon avis, de placer le fragment de code qui contient la boucle dans une méthode séparée et de simplement return d'elle.

Par exemple, changez ceci :

someLabel:
for (int j = 0; j < 5; j++)
{
    // do something
    if ...
        break someLabel;
}

dans ceci :

private void Foo() {
    for (int j = 0; j < 5; j++)
    {
        // do something
        if ...
            return;
    }
}

C'est également plus idiomatique pour les développeurs maîtrisant d'autres langages qui pourraient travailler avec votre code à l'avenir (ou futur vous ).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X