Ich habe mich gefragt, ob es eine "schlechte Praxis" ist, eine break
Anweisung zum Verlassen einer Schleife zu verwenden, anstatt die Schleifenbedingung zu erfüllen.
Ich habe nicht genug Einblick in Java und die JVM, um zu wissen, wie eine Schleife behandelt wird, und habe mich gefragt, ob ich dabei etwas Kritisches übersehen habe.
Der Fokus dieser Frage: Gibt es einen bestimmten Leistungsaufwand?
break
durch einenif
um den gesamten Rest des Codes ersetzen . So wird es in einigen anderen Sprachen gemacht, die faschistisch dem Paradigma der "strukturierten Programmierung" folgen. Der Code sieht schrecklich aus.Antworten:
Guter Herr, nein. Manchmal besteht die Möglichkeit, dass in der Schleife etwas auftritt, das die Gesamtanforderung erfüllt, ohne die logische Schleifenbedingung zu erfüllen. In diesem Fall
break
wird verwendet, um zu verhindern, dass Sie sinnlos um eine Schleife fahren.Beispiel
String item; for(int x = 0; x < 10; x++) { // Linear search. if(array[x].equals("Item I am looking for")) { //you've found the item. Let's stop. item = array[x]; break; } }
Was macht in diesem Beispiel mehr Sinn. Setzen Sie die Schleife jedes Mal auf 10 fort, auch nachdem Sie sie gefunden haben, oder wiederholen Sie die Schleife, bis Sie den Gegenstand gefunden haben und anhalten? Oder um es in reale Begriffe zu fassen; Wenn Sie Ihre Schlüssel finden, suchen Sie weiter?
Als Antwort auf einen Kommentar bearbeiten
Warum setzen nicht
x
auf11
die Schleife zu brechen? Es hat keinen Sinn. Wir habenbreak
! Wenn Ihr Code nicht davon ausgeht, dass erx
definitiv größer ist als10
später (und wahrscheinlich auch nicht), können Sie ihn nur verwendenbreak
.Der Vollständigkeit halber bearbeiten
Es gibt definitiv andere Möglichkeiten zu simulieren
break
. Fügen Sie beispielsweise Ihrer Beendigungsbedingung in Ihrer Schleife zusätzliche Logik hinzu. Zu sagen, dass es entweder sinnlos ist oder verwendet wird,break
ist nicht fair. Wie bereits erwähnt, kann eine while-Schleife häufig ähnliche Funktionen erzielen. Folgen Sie beispielsweise dem obigen Beispiel.while(x < 10 && item == null) { if(array[x].equals("Item I am looking for")) { item = array[x]; } x++; }
Mit
break
einfach bedeutet, dass Sie diese Funktionalität mit einerfor
Schleife erreichen können. Dies bedeutet auch, dass Sie nicht immer Bedingungen in Ihre Beendigungslogik einfügen müssen, wenn Sie möchten, dass sich die Schleife anders verhält. Zum Beispiel.for(int x = 0; x < 10; x++) { if(array[x].equals("Something that will make me want to cancel")) { break; } else if(array[x].equals("Something else that will make me want to cancel")) { break; } else if(array[x].equals("This is what I want")) { item = array[x]; } }
Anstatt einer
while loop
mit einer Kündigungsbedingung, die so aussieht:while(x < 10 && !array[x].equals("Something that will make me want to cancel") && !array[x].equals("Something else that will make me want to cancel"))
quelle
while(x < 10 && item == null)
Wenn Sie Lust haben, verwenden Sie einen Iterator.Chris
ist das Verständnis von OP.x
Index im Code unterhalb der Schleife verwenden möchte ? zBfound string at index x
Die Verwendung
break
, wie praktisch jede andere Sprachfunktion, kann in einem bestimmten Kontext, in dem Sie sie eindeutig missbrauchen, eine schlechte Praxis sein. Einige sehr wichtige Redewendungen können jedoch nicht ohne sie codiert werden oder würden zumindest zu einem weitaus weniger lesbaren Code führen. In diesen Fällenbreak
ist der Weg zu gehen.Mit anderen Worten, hören Sie nicht auf pauschale, uneingeschränkte Ratschläge - über
break
oder irgendetwas anderes. Es ist nicht ein einziges Mal, dass ich Code völlig abgemagert gesehen habe, nur um eine "gute Praxis" buchstäblich durchzusetzen.In Bezug auf Ihre Bedenken hinsichtlich des Leistungsaufwands gibt es absolut keine. Auf Bytecode-Ebene gibt es sowieso keine expliziten Schleifenkonstrukte: Die gesamte Flusssteuerung wird in Form von bedingten Sprüngen implementiert.
quelle
Das JLS gibt an, dass eine Unterbrechung eine abnormale Beendigung einer Schleife ist. Nur weil es als abnormal angesehen wird, bedeutet dies nicht, dass es nicht in vielen verschiedenen Codebeispielen, Projekten, Produkten, Space Shuttles usw. verwendet wird. Die JVM-Spezifikation gibt weder das Vorhandensein noch das Fehlen eines Leistungsverlusts an, obwohl dies der Fall ist Die Ausführung des Löschcodes wird nach der Schleife fortgesetzt.
Die Lesbarkeit des Codes kann jedoch durch ungerade Unterbrechungen beeinträchtigt werden. Wenn Sie eine Unterbrechung in einer komplexen if-Anweisung festhalten, die von Nebenwirkungen und seltsamem Bereinigungscode umgeben ist, möglicherweise mit einer mehrstufigen Unterbrechung mit einem Label (oder schlimmer noch mit einer Reihe seltsamer Beendigungsbedingungen nacheinander), wird dies nicht der Fall sein für jeden leicht lesbar sein.
Wenn Sie Ihre Schleife unterbrechen möchten, indem Sie die Iterationsvariable außerhalb des Iterationsbereichs erzwingen oder auf andere Weise eine nicht unbedingt direkte Methode zum Beenden einführen, ist sie weniger lesbar als
break
.Es ist jedoch fast immer eine schlechte Praxis , zusätzliche Zeiten auf leere Weise zu wiederholen, da zusätzliche Iterationen erforderlich sind und möglicherweise unklar sind.
quelle
Meiner Meinung nach sollte eine
For
Schleife verwendet werden, wenn eine feste Anzahl von Iterationen durchgeführt wird und diese nicht gestoppt werden, bevor jede Iteration abgeschlossen ist. In dem anderen Fall, in dem Sie früher beenden möchten, bevorzuge ich die Verwendung einerWhile
Schleife. Selbst wenn Sie diese beiden kleinen Wörter lesen, scheint es logischer. Einige Beispiele:for (int i=0;i<10;i++) { System.out.println(i); }
Wenn ich diesen Code schnell lese, weiß ich sicher, dass er 10 Zeilen ausdruckt und dann weitergeht.
for (int i=0;i<10;i++) { if (someCondition) break; System.out.println(i); }
Dieser ist mir schon weniger klar. Warum würden Sie zuerst angeben, dass Sie 10 Iterationen durchführen werden, aber dann innerhalb der Schleife einige zusätzliche Bedingungen hinzufügen, um früher zu stoppen?
Ich bevorzuge das vorherige Beispiel, das auf diese Weise geschrieben wurde (auch wenn es etwas ausführlicher ist, aber nur mit 1 Zeile mehr):
int i=0; while (i<10 && !someCondition) { System.out.println(i); i++; }
Jeder, der diesen Code liest, wird sofort feststellen, dass es eine zusätzliche Bedingung gibt, die die Schleife möglicherweise früher beendet.
Natürlich können Sie in sehr kleinen Schleifen immer diskutieren, dass jeder Programmierer die break-Anweisung bemerkt. Aber ich kann aus eigener Erfahrung sagen, dass in größeren Schleifen diese Pausen überwacht werden können. (Und das bringt uns zu einem anderen Thema, um Code in kleinere Teile aufzuteilen.)
quelle
Die Verwendung von Break-In-Schleifen kann durchaus legitim sein und sogar die einzige Möglichkeit sein, einige Probleme zu lösen.
Der schlechte Ruf beruht jedoch auf der Tatsache, dass neue Programmierer ihn normalerweise missbrauchen, was zu verwirrendem Code führt, insbesondere durch die Verwendung von break, um die Schleife unter Bedingungen zu stoppen, die möglicherweise überhaupt in die Schleifenbedingungsanweisung geschrieben wurden.
quelle
while(true)
und dannbreak
unter bestimmten Bedingungen s.Nein, es ist keine schlechte Praxis, aus einer Schleife auszubrechen, wenn eine bestimmte gewünschte Bedingung erreicht ist (wie wenn eine Übereinstimmung gefunden wird). Oft möchten Sie möglicherweise die Iterationen stoppen, weil Sie bereits das erreicht haben, was Sie möchten, und es keinen Sinn macht, weiter zu iterieren. Achten Sie jedoch darauf, dass Sie nicht versehentlich etwas verpassen oder ausbrechen, wenn dies nicht erforderlich ist.
Dies kann auch zu einer Leistungsverbesserung beitragen, wenn Sie die Schleife unterbrechen, anstatt über Tausende von Datensätzen zu iterieren, selbst wenn der Zweck der Schleife abgeschlossen ist (dh möglicherweise besteht die Übereinstimmung mit dem erforderlichen Datensatz bereits).
Beispiel:
for (int j = 0; j < type.size(); j++) { if (condition) { // do stuff after which you want break; // stop further iteration } }
quelle
search: for (int i = 0; i < s; i++) { for (int j = 0; j < t.size(); j++) { if (condition) { break search; } } }
Es ist keine schlechte Praxis, aber es kann dazu führen, dass Code weniger lesbar ist. Eine nützliche Umgestaltung, um dies zu umgehen, besteht darin, die Schleife in eine separate Methode zu verschieben und dann anstelle einer Unterbrechung eine return-Anweisung zu verwenden, z. B. diese (Beispiel aus der Antwort von @ Chris):
String item; for(int x = 0; x < 10; x++) { // Linear search. if(array[x].equals("Item I am looking for")) { //you've found the item. Let's stop. item = array[x]; break; } }
kann dazu (mit der Extraktionsmethode ) umgestaltet werden :
public String searchForItem(String itemIamLookingFor) { for(int x = 0; x < 10; x++) { if(array[x].equals(itemIamLookingFor)) { return array[x]; } } }
Was sich beim Aufrufen aus dem umgebenden Code als besser lesbar erweisen kann.
quelle
Wenn Sie anfangen, so etwas zu tun, wird es etwas seltsam und Sie sollten es besser auf eine separate Methode verschieben,
returns
die sich aus der angepassten Bedingung ergibt.boolean matched = false; for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { if(matchedCondition) { matched = true; break; } } if(matched) { break; } }
Um zu erläutern, wie der obige Code bereinigt wird, können Sie den Code umgestalten und in eine Funktion verschieben, die
returns
nicht verwendet wirdbreaks
. Dies ist im Allgemeinen besser im Umgang mit komplexen / chaotischenbreaks
.public boolean matches() for(int i = 0; i < 10; i++) { for(int j = 0; j < 10; j++) { if(matchedCondition) { return true; } } } return false; }
Allerdings für etwas Einfaches wie mein Beispiel unten. Auf jeden Fall benutzen
break
!for(int i = 0; i < 10; i++) { if(wereDoneHere()) { // we're done, break. break; } }
Wenn Sie im obigen Fall die Bedingungen
i
undj
den Wert ändern , wird der Code nur schwer lesbar. Es könnte auch einen Fall geben, in dem die Obergrenzen (im Beispiel 10) Variablen sind, sodass es noch schwieriger ist zu erraten, auf welchen Wert sie gesetzt werden müssen, um die Schleife zu verlassen. Man könnte natürlich einfach eingestellti
undj
auf Integer.MAX_VALUE, aber ich denke , Sie dies beginnt sehen chaotisch sehr schnell. :) :)quelle
break
Aussagen inreturn
Aussagen umwandeln .goto
, aber dies ist einer der Fälle, in denen das besonders nützlich ist.Es gibt eine Reihe gängiger Situationen, für die
break
der Algorithmus am natürlichsten ausgedrückt werden kann. Sie werden "eineinhalb Schleifen" -Konstrukte genannt; Das Paradigmenbeispiel istwhile (true) { item = stream.next(); if (item == EOF) break; process(item); }
Wenn Sie dies nicht verwenden
break
können, müssen Sie sich stattdessen wiederholen:item = stream.next(); while (item != EOF) { process(item); item = stream.next(); }
Es besteht allgemein Einigkeit darüber, dass dies schlimmer ist.
In ähnlicher Weise
continue
gibt es ein allgemeines Muster, das so aussieht:for (item in list) { if (ignore_p(item)) continue; if (trivial_p(item)) { process_trivial(item); continue; } process_complicated(item); }
Dies ist oft besser lesbar als die Alternative mit verkettet
else if
, insbesondere wennprocess_complicated
mehr als nur ein Funktionsaufruf vorliegt.Weiterführende Literatur: Loop-Exits und strukturierte Programmierung: Wiedereröffnung der Debatte
quelle
Nein, das ist keine schlechte Praxis. Dies ist der einfachste und effizienteste Weg.
quelle
logic
. Manchmal möchten Sie eine Schleife aufgrund eines Flags oder Ähnlichem abnormal beenden. In diesem Fallbreak
ist eine gute Option.Es ist zwar keine schlechte Praxis, Pause zu verwenden, und es gibt viele hervorragende Verwendungsmöglichkeiten dafür, aber es sollte nicht alles sein, worauf Sie sich verlassen können. Fast jede Verwendung einer Unterbrechung kann in die Schleifenbedingung geschrieben werden. Code ist weitaus besser lesbar, wenn reale Bedingungen verwendet werden. Bei einer langen oder Endlosschleife sind Unterbrechungen jedoch durchaus sinnvoll. Sie sind auch bei der Suche nach Daten sinnvoll, wie oben gezeigt.
quelle
Wenn Sie im Voraus wissen , wo wird die Schleife zu stoppen, wird es wahrscheinlich die Lesbarkeit des Codes verbessern den Zustand , in dem zu erklären
for
,while
oder`do-while
Schleife.Ansonsten ist das der genaue Anwendungsfall für
break
.quelle
break
undcontinue
bricht die Lesbarkeit für den Leser, obwohl es oft nützlich ist. Nicht so sehr wie "goto" -Konzept, aber fast.Wenn Sie einige neue Sprachen wie Scala (inspiriert von Java und funktionale Programmiersprachen wie Ocaml) verwenden, werden Sie dies bemerken
break
undcontinue
einfach verschwinden.Insbesondere bei der funktionalen Programmierung wird dieser Codestil vermieden:
Warum unterstützt Scala Break and Continue nicht?
Zusammenfassend:
break
undcontinue
werden in Java häufig für einen imperativen Stil verwendet, aber für alle Codierer, die früher funktionale Programmierung praktizierten, könnte es seltsam sein.quelle