Pourquoi le compilateur ne met-il pas automatiquement des instructions break après chaque bloc de code dans le commutateur? Est-ce pour des raisons historiques? Quand voudriez-vous que plusieurs blocs de code s'exécutent?
94
Pourquoi le compilateur ne met-il pas automatiquement des instructions break après chaque bloc de code dans le commutateur? Est-ce pour des raisons historiques? Quand voudriez-vous que plusieurs blocs de code s'exécutent?
break
.Réponses:
Parfois, il est utile d'avoir plusieurs cas associés au même bloc de code, tels que
etc. Juste un exemple.
D'après mon expérience, il est généralement mauvais de «passer à travers» et d'exécuter plusieurs blocs de code pour un cas, mais il peut y avoir des utilisations pour cela dans certaines situations.
la source
// Intentional fallthrough.
lorsque vous omettez une pause. Ce n'est pas tant un mauvais style que "facile d'oublier une pause accidentellement" à mon avis. PS Bien sûr pas dans des cas simples comme dans la réponse elle-même.case
s sont empilés de cette façon. S'il y a du code entre eux, oui, le commentaire est probablement mérité.case
, comme cecicase 'A','B','C': doSomething(); case 'D','E': doSomethingElse();
:, sans avoir besoin d'une pause entre les cas. Pascal pourrait faire cela: "L'instruction case compare la valeur de l'expression ordinale à chaque sélecteur, qui peut être une constante, un sous-intervalle ou une liste d'entre eux séparés par des virgules." ( wiki.freepascal.org/Case )Historiquement , c'est parce que le
case
définissait essentiellement unlabel
, également connu comme le point cible d'ungoto
appel. L'instruction switch et ses cas associés ne représentent en réalité qu'une branche à plusieurs voies avec plusieurs points d'entrée potentiels dans un flux de code.Cela dit, il a été noté un nombre presque infini de fois que
break
c'est presque toujours le comportement par défaut que vous préférez avoir à la fin de chaque cas.la source
Java vient de C et c'est la syntaxe de C.
Il y a des moments où vous souhaitez que plusieurs instructions case n'aient qu'un seul chemin d'exécution. Vous trouverez ci-dessous un exemple qui vous indiquera le nombre de jours par mois.
la source
Je pense que c'est une erreur. En tant que construction de langage, il est tout aussi facile à avoir
break
que la valeur par défaut et à la place d'avoir unfallthrough
mot - clé. La plupart du code que j'ai écrit et lu a une pause après chaque cas.la source
continue <case name>
ce qui permet de spécifier explicitement avec quelle déclaration de cas continuer;case
dans le courantswitch
, cela devient simplement ungoto
. ;-)Vous pouvez faire toutes sortes de choses intéressantes avec la chute des cas.
Par exemple, disons que vous voulez faire une action particulière pour tous les cas, mais dans un certain cas, vous voulez faire cette action plus autre chose. L'utilisation d'une instruction switch avec fall-through rendrait les choses assez faciles.
Bien sûr, il est facile d'oublier l'
break
instruction à la fin d'un cas et de provoquer un comportement inattendu. Les bons compilateurs vous avertiront lorsque vous omettez l'instruction break.la source
Laissant de côté la bonne volonté de pouvoir utiliser le même bloc pour plusieurs cas (qui pourraient être à cas particulier) ...
C'est principalement pour la compatibilité avec C, et c'est sans doute un ancien hack de l'époque où les
goto
mots - clés parcouraient la terre. Il ne permettra des choses étonnantes, bien sûr, comme le dispositif de Duff , mais que ce soit un point en sa faveur ou contre est ... argumentative au mieux.la source
Le
break
commutateur aftercase
est utilisé pour éviter la chute dans les instructions switch. Bien que cela soit intéressant, cela peut maintenant être réalisé grâce aux nouvelles étiquettes de commutation mises en œuvre via JEP-325 .Avec ces changements, le
break
avec chaque commutateurcase
peut être évité comme démontré plus loin: -Lors de l' exécution du code ci-dessus avec JDK-12 , la sortie comparative pourrait être considérée comme
et
et bien sûr la chose inchangée
la source
Vous n'avez donc pas à répéter le code si vous avez besoin de plusieurs cas pour faire la même chose:
Ou vous pouvez faire des choses comme:
En cascade.
Vraiment sujet aux bogues / confusion, si vous me demandez.
la source
do this
etdo that
pour ceci mais justedo that
pour cela?En ce qui concerne le dossier historique, Tony Hoare a inventé l'énoncé de cas dans les années 1960, pendant la révolution de la «programmation structurée». La déclaration de cas de Tony prenait en charge plusieurs étiquettes par cas et une sortie automatique sans
break
déclarations puantes . L'exigence d'un explicitebreak
était quelque chose qui sortait de la ligne BCPL / B / C. Dennis Ritchie écrit (dans ACM HOPL-II):Je n'ai pas pu trouver d'écrits historiques sur BCPL, mais le commentaire de Ritchie suggère que
break
c'était plus ou moins un accident historique. BCPL a résolu le problème plus tard, mais peut-être que Ritchie et Thompson étaient trop occupés à inventer Unix pour être dérangés par un tel détail :-)la source
break
autorise "l'exécution de plusieurs blocs de code", et se préoccupe davantage de la motivation de ce choix de conception. D'autres ont mentionné l'héritage bien connu de C à Java, et cette réponse a poussé la recherche encore plus loin aux jours pré-C. J'aurais aimé avoir cette correspondance de motifs (bien que très primitive) dès le début.Java est dérivé de C, dont l'héritage comprend une technique connue sous le nom de Duff's Device . C'est une optimisation qui repose sur le fait que le contrôle passe d'un cas à l'autre, en l'absence de
break;
déclaration. Au moment où C a été normalisé, il y avait beaucoup de code comme celui-là "dans la nature", et il aurait été contre-productif de changer le langage pour casser de telles constructions.la source
Comme les gens l'ont déjà dit, il s'agit de permettre des retombées et ce n'est pas une erreur, c'est une fonctionnalité. Si trop d'
break
instructions vous ennuient, vous pouvez facilement vous en débarrasser en utilisant desreturn
instructions à la place. C'est en fait une bonne pratique, car vos méthodes doivent être aussi petites que possible (pour des raisons de lisibilité et de maintenabilité), donc uneswitch
instruction est déjà assez grande pour une méthode, par conséquent, une bonne méthode ne doit contenir rien d'autre, c'est un exemple:L'exécution imprime:
comme prévu.
la source
Le fait de ne pas avoir de pause automatique ajoutée par le compilateur permet d'utiliser un commutateur / cas pour tester des conditions comme
1 <= a <= 3
en supprimant l'instruction break de 1 et 2.la source
car il y a des situations où vous souhaitez parcourir le premier bloc par exemple pour éviter d'écrire le même code dans plusieurs blocs mais être toujours capable de les diviser pour le contrôle mroe. Il y a aussi une tonne d'autres raisons.
la source
C'est une vieille question, mais en fait, je suis tombé sur l'utilisation du cas sans déclaration de rupture aujourd'hui. Ne pas utiliser break est en fait très utile lorsque vous devez combiner différentes fonctions en séquence.
par exemple en utilisant des codes de réponse http pour authentifier l'utilisateur avec un jeton de temps
code de réponse du serveur 401 - le jeton est obsolète -> régénérer le jeton et connecter l'utilisateur.
code de réponse du serveur 200 - le jeton est OK -> connecter l'utilisateur.
dans les déclarations de cas:
En utilisant cela, vous n'avez pas besoin d'appeler la fonction utilisateur de connexion pour la réponse 401 car lorsque le jeton est régénéré, le runtime saute dans le cas 200.
la source
Vous pouvez facilement séparer d'autres types de nombre, de mois, de décompte.
C'est mieux alors si dans ce cas;
la source
Je travaille maintenant sur un projet dont j'ai besoin
break
dans mon instruction switch, sinon le code ne fonctionnera pas. Soyez avec moi et je vais vous donner un bon exemple de pourquoi vousbreak
en avez besoin dans votre déclaration de changement.Imaginez que vous ayez trois états, l'un qui attend que l'utilisateur entre un nombre, le second pour le calculer et le troisième pour imprimer la somme.
Dans ce cas, vous avez:
En regardant les états, vous voudriez que l'ordre d'exaction commence sur state1 , puis state3 et enfin state2 . Sinon, nous n'imprimerons que les entrées des utilisateurs sans calculer la somme. Juste pour clarifier à nouveau, nous attendons que l'utilisateur entre une valeur, puis calculons la somme et imprime la somme.
Voici un exemple de code:
Si nous ne l'utilisons pas
break
, il s'exécutera dans cet ordre, état1 , état2 et état3 . Mais en utilisantbreak
, nous évitons ce scénario, et pouvons commander dans la bonne procédure qui est de commencer par state1, puis state3 et last but not least state2.la source
Exactement, car avec un placement intelligent, vous pouvez exécuter des blocs en cascade.
la source