2010-08-18 28 views
17

Ich bin Informatikstudent, deshalb weiß ich nicht viel.Verschiedene Arten von Programmablauf?

Ich habe kürzlich mit einem Freund gesprochen, der gerade einen Job als (Java) Softwareentwickler bekommen hat. Er erzählte mir, dass es in seinem Job einen Typ gibt, der sehr erfahren in C++ ist, aber leider jedes Mal, wenn er Code in Java schreibt, benutzt er den Try-Catch, um den Fluss des Programms zu kontrollieren. Laut meinem Freund ist das in Java ein falscher Stil. Ist das wahr? Was sind die Unterschiede (wenn überhaupt) in try-catch (-finally in Java) zwischen C++ und Java?

+1

+1 zu John Weldon's Antwort. Beachten Sie, dass einer der wirklich unangenehmen Aspekte eines Teils des Java-Ökosystems (und das ist eine Java-Spezifität) die übermäßige Verwendung von ** checked ** -Ausnahmen durch einige APIs/Framework ist. Grundsätzlich erzwingen die API-Benutzer, den Fluss ihres Programms zu kontrollieren, indem sie eine sinnlose, überprüfungsfreie Ausnahme für Dinge fangen, die überhaupt nicht außergewöhnlich sind. Ein gewisser Rahmen, wie der Frühling, ist richtig gestaltet und missbilligt diese furchtbar schlechte Praxis. Joshua Bloch in seinem * Effective Java * empfiehlt, eine "State Testing Methode" zu bevorzugen, um unnötige Ausnahmen zu umgehen. – NoozNooz42

+0

Hallo Danke für die Antwort. "Erzwingt im Grunde die API-Benutzer, den Fluss ihres Programms zu kontrollieren, indem sie sinnlose, überprüfungsfreie Ausnahme für Dinge fangen, die überhaupt nicht außergewöhnlich sind." Also das ist der Unterschied in try-catch zwischen C++/Java? Was meinst du mit "checked" Ausnahmen? Prost – Muggen

+1

Siehe http://www.javapractices.com/topic/TopicAction.do?Id=129. Geprüfte Ausnahmen sind im Wesentlichen ein Missbrauch von Ausnahmen für eine nicht außergewöhnliche Flusskontrolle. Sie sind auch ein Wartungsalbtraum. –

Antwort

28

Verwenden von Try-Catch, um den Fluss des Programms zu steuern, ist irgendwo falsch ... Exception Handhabung ist, was es sagt: Handhabung von Ausnahme Umstände.

Natürlich gibt es für jede Regel ein Dutzend Gegenbeispiele für notwendige Abweichungen, aber generell: Kontrolliere den Programmablauf nicht mit Ausnahmen.

Das Verwenden von Ausnahmen zum Steuern des Programmflusses tritt auf, wenn Sie erwarten, dass bestimmte Ausnahmen in einer normalen Betriebsumgebung ausgelöst werden, und Sie basierend auf diesen Ausnahmen logische Entscheidungen treffen.

Zum Beispiel der Steuerung des Programmablaufes in Pseudo-Code:

try { 
    write update to file 
} catch (IOException) { 
    write update to alternate file 
} 

In diesem Fall wäre es besser, tatsächlich für den Pfad Existenz zu testen, bevor die Schreib blind durchgeführt wird.

entfernte ich die Erlaubnis, die Prüfung der Anmerkungen, weil es ein schlechtes Beispiel ist

Eine gute Nutzung der Ausnahmebehandlung: (wieder Pseudo-Code)

try { 
    do stuff 
} catch(OutOfMemoryException) { 
    fail gracefully (don't try and do something else to achieve the same result) 
} 
+1

Hallo. Danke für die Antwort. Wäre es möglich, Code zu zeigen, wo ein Try-Catch den Fluss steuert, und einen ähnlichen Fall, in dem es nicht funktioniert? Danke – Muggen

+2

Das ist eine wirklich gute Frage @Muggen; Ich werde es versuchen, meine Antwort zu aktualisieren, aber ich denke, das ist eine eigene Frage wert. –

+3

@Muggen Wenn Sie eine offene Datei haben, sollten Sie in der Lage sein zu lesen, aber wenn Sie dies nicht ein Ausnahmefall können. Wenn ein Benutzer versucht sich anzumelden, aber ein ungültiges Passwort eingibt, ist dies eine normale Flussbedingung und sollte so behandelt werden, nicht mit try-catch. –

-2

Ihre Frage ohne Beispielcode zu vage ist. In C++ gibt es keine finally.

BEARBEITEN Im Allgemeinen möchten Sie nicht exceptions als Mittel verwenden, um den Fluss zu steuern. Exceptions sollen nur für außergewöhnliche (unerwartete Situationen) Fälle verwendet werden.

+1

Tatsächlich beginnt diese Antwort die "andere" Frage zu beantworten, die das OP gestellt hat: Was sind die Unterschiede in der Ausnahmebehandlung zwischen Java und C++? –

+0

Das ist eine gute Antwort, +1. – fastcodejava

8

Ich würde sagen, dass aus Sicht der Programmarchitektur der Zweck der Ausnahmen in Java und C++ identisch ist. Sie sollten verwendet werden, um Ausnahmefälle zu behandeln, nicht den direkten Ablauf des Programms.

Das häufigste Argument gegen die Verwendung von Ausnahmen ist, dass sie langsam sind. Wie die meisten Argumente, die auf der Code-Geschwindigkeit basieren, ist es heutzutage fast immer irrelevant, besonders wenn Exceptions richtig verwendet werden.

+0

Hallo. "... vor allem, wenn Ausnahmen ordnungsgemäß verwendet werden." Wie kann eine Ausnahme falsch verwendet werden? – Muggen

+2

Wann immer es verwendet wird, um den Fluss des Programms zu steuern, anstatt Ausnahmefälle zu behandeln. Wenn Sie z. B. die Länge eines Arrays überprüfen können, verwenden Sie keine Außer-Grenze-Ausnahme, um zu wissen, dass Sie die Länge des Arrays für den Index übergeben haben, sondern lassen Sie die for-Schleife einfach am entsprechenden Punkt enden. – aperkins

+3

In diesem Fall ist "sie sind langsam" eine Art Proxy-Argument für "das ist nicht, wofür sie sind". Manche Menschen können nicht so gut über symbolische Überlegungen auf höherer Ebene sprechen, also müssen Sie ihnen Beispiele geben. Wenn Sie Dinge verwenden, die weit über den eigentlichen Verwendungszweck hinausgehen, treten Probleme auf (langsam zu sein, weil ein Beispiel dafür verwendet wird). Wenn jemand die Langsamkeit repariert, stimmt immer noch nicht alles mit der Welt. –

4

Ich würde das C erwarten ++ und Java Welten weitgehend in ihren Ansichten ähnlich zu sein:

  1. Flusssteuerung mit try/catch-Blöcke ist nicht sofort offensichtlich
  2. es ist teuer leistungsmäßig. In der Praxis mag das kein Problem sein, aber in vielen Szenarien (z. B. engen Schleifen) wird es sicherlich Auswirkungen auf Sie haben.
6

Ich denke, was er sagt, ist, dass er Ausnahmen für nicht außergewöhnliche Bedingungen wie normale Loop-Abschlüsse verwendet.Dies wird von Programmierern in den meisten Sprachen, die Ausnahmen, einschließlich C++, vorsehen, als No-No betrachtet.

Der Grund dafür ist, dass Ausnahmen dazu neigen, ein gutes Stück Information mit sich zu ziehen. Auf einigen Plattformen bringen sie den gesamten Callstack an den Punkt der Ausnahme, um ihn in einer netten Debug-Nachricht anzuzeigen. Das ist sehr teuer, wenn du nur einen unbedingten Kontrollsprung willst.

Stattdessen sollten Sie Aussagen wie break, return oder sogar (in einer echten Prise) goto verwenden.

+2

Auf der anderen Seite ist dies ein "ja-ja" in Python, wobei ** jede for-Schleife ** durch Behandlung einer StopIteration-Ausnahme beendet wird. ;) – UncleBens

+2

@UncleBens - Vielen Dank für die Bestätigung meiner Wischwaschheit. Ich dachte mir, da draußen muss mindestens einer sein. :-) –

2

Der try-catch-Block soll in allen Sprachen dasselbe bewirken - Ausnahmen sind eine der vielen Möglichkeiten zur Wiederherstellung, wenn etwas schief geht. In Java sind die beiden folgenden Anweisungen identisch:

if(x != null){ 
    //do the normal thing 
} 
else{ 
    //recover from the error 
} 

und

try{ 
    //do the normal thing 
} 
catch(NullPointerException ex){ 
    //recover 
} 

jedoch für eine Reihe von Gründen Ausnahmen ist nie gute Idee, mit:

  • die Kosten, die mit Wurf zugeordnet die Ausnahme (dh die Generierung eines Throwable in Java)
  • der Ablauf der Kontrolle ist nicht sofort offensichtlich - zum Beispiel, wenn eine NullPointerException sein kann durch mehrere Anweisungen im try-Block geworfen, wie kann man sagen, die man wirft ihn in dem catch-Block
  • etc, etc
+0

Hallo. Danke für die Antwort. "Wie kannst du sagen, wer es in den Fangblock geworfen hat" ist eine andere Frage, die ich hatte. Sie schlagen also vor, Try-Catch nur in speziellen Fällen einzusetzen oder falsch zu verstehen? Prost – Muggen

+0

Seien Sie vorsichtig, wenn Sie sagen, dass diese Konstrukte identisch oder äquivalent sind. Wenn "// tue das normale Ding" zuerst etwas tut, das nicht die "Null" -Referenz falsch verwendet, dann wird das zweite Beispiel einige Arbeit (möglicherweise mit sichtbaren Nebenwirkungen) tun, die im ersten Beispiel nicht vorkommen wird. –

+0

Warte, es ist "nie" eine gute Idee ?! Ausnahmen sind ideal für das, wofür sie bestimmt sind: Ausnahmen. Anders als Ergebniscodes können sie nicht ignoriert werden, und sie blähen sich automatisch auf, bis sie Code finden, der bereit ist, mit ihnen umzugehen. Sag niemals nie, besonders über Dinge mit einem genau definierten Gebrauch. –

3

Der Sohle Zweck try/catch ist Flusskontrolle. Es soll uns ermöglichen, aus jeder Schleife auszubrechen und sogar über den Aufrufer hinaus zu einer übergeordneten Funktion zu gelangen.

Es wurde jedoch für außergewöhnliche Bedingungen entwickelt, z. B. die Verwendung von Nullreferenzen, das Überlaufen von Divisionen oder das Fehlschlagen von Datei-E/A. Dies sind Fehler, die verhindern, dass das Programm weiter läuft und muss behandelt werden. Im Allgemeinen sind sie schwer vorherzusagen oder sind sehr selten.

Wenn ein außergewöhnlicher Zustand auftritt, ist es das Beste, den Steuerungsfluss so zu ändern, dass die Ausnahme so weit nach oben geworfen wird, wie es sein muss, um einen Catch-Block zu finden. Jede dazwischenliegende Methode wird abgebrochen und abgewickelt, auch wenn sie keinen Code enthält, um nach Ergebnissen zu suchen.

Wenn die Leute beschweren sich über try/catch für die Flusssteuerung verwenden, was sie sollte Mittelwert ist, dass es nicht für die Ablaufsteuerung in nicht-außergewöhnlichen Bedingungen ist. Wenn Sie nur eine Schleife beenden möchten, verwenden Sie break oder return; Werfen Sie keine Ausnahme und fangen Sie sie dann ab. Dafür gibt es keine Ausnahmen, und dafür sind sie auch nicht gut.

+0

Gute Erklärung @Steven. Ich bin mir nicht sicher, ob es sich gelohnt hat meine Antwort zu verwerfen, aber trotzdem gut :) –

+0

@John: Du hast 20 upvotes. Der eine downvote wird zumindest bekommen Leute zu stoppen und Alternativen zu betrachten. –

1

Was er sein will, ist es, mehrere Möglichkeiten, um nicht ein Stück Code ausführen ... so statt (in Java)

if (cond1) { 
    some_code(); 
    if (cond2) { 
    some_more_code(); 
    if (condN) { 
     ad_infinitum 
    } 
    } 
} 

Dies kann durch das Werfen einig Mülls ‚abgeflachte‘ wird ...

try { 
    if (!cond1) throw new Throwable(); 
    some_code(); 
    if (!cond2) throw new Throwable(); 
    some_more_code(); 
    if (!condN) throw new Throwable(); 
    ad_infinitum(); 
} catch (Throwable ignore) { } 

Das Problem ist, was ist, wenn eine echte Ausnahme geworfen wurde?Ich denke, was Ihr Kollege sollte schreiben, wenn er will, ist die Vertiefung abzuflachen etwas wie folgt aus:

do { 
    if (!cond1) break; 
    some_code(); 
    if (!cond2) break; 
    some_more_code(); 
    if (!condN) break; 
    ad_infinitum(); 
} while (false); 

Da do/while immer ausführt wir die Pause nutzen können eine goto (so lange zu nähern, da sie alle auf das geht gleicher Ort).

Verwandte Themen