Wann try.catch nutzen?

Status
Nicht offen für weitere Antworten.

GambaJo

Mitglied
Ich arbeite schon sehr lange mit prozeduralen Programmiersprachen und frische nun mit Java meine OOP-Kenntnisse wieder etwas auf.

Dabei ist mir eine Frage gekommen: In welchen Fällen nutzt man try/catch-Blöcke?

Habe mir manche Code-Schnipsel angeschaut, an manchen Stellen wird try/catch genutzt, und manchmal nicht. Rein theoretisch kann zu ziemlich überall ein Fehler auftreten. So müsste im Prinzip alles per try/catch abgefangen werden. Wird es aber nicht.

Gibt es ein Muster oder eine Regel für die Nutzung von try/catch? Wenn nicht, wann ist es sinnvoll es zu nutzen, und wann nicht?
 

musiKk

Top Contributor
Man benutzt es immer dann, wenn man eine Funktion aufruft, die eine Exception werfen koennte, auf die die aufrufende Funktion reagieren kann. Die Alternative ist weiterwerfen per throws. Das gilt halt vor allem fuer checked Exceptions. Da muss eine der beiden Moeglichkeiten verwendet werden, sonst kompilierts nicht.
 

Landei

Top Contributor
Im Prinzip solltest du try-catch es immer dann nutzen, wenn du etwas sinnvolles tun kannst. Z.B. wenn du eine IOException bekommen kannst, könntest du sie dort abfangen, wo du den Nutzer darüber informieren kannst. Anderes Beispiel: Bibliotheken reichen Fehler meist weiter, weil sie selber gar nicht wissen, was eine "sinnvolle" Reaktion wäre.
Oft wird auch eine Exception abgefangen und im catch-Block dafür eine andere ausgelöst, also die Original-Exception gewissermaßen in eine andere "übersetzt", die im Kontext des aktuellen Programms "sinnvoller" ist (z.B. könnte man eine Exception vom SAX-Parser in eine IOException umwandeln, um sie im Programm einheitlich mit anderen Lese-Problemen zu behandeln).
 

Marco13

Top Contributor
Kurze Anwort: In Ausnahmefällen :wink:

Mittlere Antwort: Wenn man die unerwüschten Folgen einer Ausnahmesituation (Exception) behandeln möchte. Vielleicht ein Beispiel - das etwas "konstruiert" und pseudocodelastig ist, aber vielleicht die Grundidee verdeutlicht:

- Der Benutzer kann einen Dateinamen angeben
- Die Datei wird geöffnet
- Der Benutzer gibt eine Zahl ein
- Die Zahl wird in die Datei geschrieben

Im Pseudocode also sowas wie
Code:
void writeUserSelectedNumberToUserSelectedFile()
{
    String fileName = benutzerGibtDateinamenEin();
    FileHandle fileHandle = openFile(fileName);
    int number = benutzerGibtZahlEin();
    fileHandle.write(number);
}
In jeder dieser Zeilen kann irgendwas schiefgehen:
- Der Dateiname kann ungültig sein (sowas wie "***:??:**") - das könnte sowas wie eine "InvalidFileNameException" (oder so) werfen
- Die Datei existiert vielleicht nicht - das wäre eine "IOException"
- Die Eingabe kann keine gültige Zahl sein (sowas wie "12XXHallo456") - also eine "NumberFormatException"
- Die Datei kann schreibgeschützt sein - nochmal "IOException"

Dann muss man sich überlegen, was in den jeweiligen Ausnahmefälllen passieren soll. Das einfachste ist, die Exceptions einfach weiterzureichen
Code:
void writeUserSelectedNumberToUserSelectedFile() throws InvalidFileNameException, NumberFormatException, IOException
{
    String fileName = benutzerGibtDateinamenEin();
    FileHandle fileHandle = openFile(fileName);
    int number = benutzerGibtZahlEin();
    fileHandle.write(number);
}
Damit bürdet man demjenigen, der diese Methode benutzen will, die Last auf, sich um jeden Fall einzeln zu kümmern. In diesem Fall wäre das vmtl. ziemlich blöd und unpraktisch. Derjenige, der diese Methode aufruft, will nicht wissen, WAS genau schiefgelaufen ist. Er kann eh nicht wirklich was dran ändern.

Eine Alternative wäre, eine neue Exception-Art zu definieren, wie z.B. eine "StupidUserException", die man "immer" wirft, wenn "irgendwas" schiefgeht:
Code:
void writeUserSelectedNumberToUserSelectedFile() throws StupidUserException
{
    try
    {
        String fileName = benutzerGibtDateinamenEin();
        FileHandle fileHandle = openFile(fileName);
        int number = benutzerGibtZahlEin();
        fileHandle.write(number);
    } 
    catch (InvalidFileNameException e)
    {
        throw new StupidUserException("Ungültiger Dateiname "+e.getMessage);
    }
    catch (IOException e)
    {
        throw new StupidUserException("Datei nicht gefunden oder schreibgeschützt "+e.getMessage);
    }
    catch (NumberFormatException e)
    {
        throw new StupidUserException("Ungültige Zahleneingabe "+e.getMessage);
    }
}

Derjenige, der jetzt die Methode aufruft, muss sich nurnoch um die "StupidUserException" kümmern. WENN so eine Exception kommt, kann er z.B. dem Benutzer in einer Dialogbox die Meldung zeigen: "Oh, bist du blöööhht" - und vielleicht noch den String, den man sich mit stupidUserExcetpion.getMessage() holen kann. Derjenige, der die Methode aufruft, "Behandelt" die Ausnahmesituation dann "so gut er kann": Er sagt dem Benutzer, dass er einen Fehler gemacht hat, und worin dieser Fehler bestand.

Die letzte Möglichkeit wäre, alle Exceptions selbst zu behandeln
Code:
void writeUserSelectedNumberToUserSelectedFile() /* throws GARNICHTS */
{
    String fileName;
    FileHandle fileHandle;
    int number;

    try
    {
        fileName = benutzerGibtDateinamenEin();
    } 
    catch (InvalidFileNameException e)
    {
        print("Ungültiger Dateiname "+e.getMessage);
        return;
    }

    try
    {
        fileHandle = openFile(fileName);
    } 
    catch (IOException e)
    {
        print("Datei nicht gefunden "+e.getMessage);
        return;
    }

    try
    {
        number = benutzerGibtZahlEin();
    } 
    catch (NumberFormatException e)
    {
        print("Ungültige Zahleneingabe "+e.getMessage);
        return;
    }

    try
    {
        fileHandle.write(number);
    } 
    catch (IOException e)
    {
        print("Datei schreibgeschützt "+e.getMessage);
        return;
    }

}
Wobei (sinngemäß) auch jeder der try-catch-Blöcke in einer Schleife stehen könnte, die so lange wiederholt, bis der Fehler NICHT mehr auftritt, oder die Methode einen boolean zurückgeben könnte, der anzeigt, ob die Methode erfolgreich abgearbeitet wurde oder nichts, usw....


Am sinnvollsten wäre in diesem (konstruierten!!!) Beispiel vermutlich die zweite Lösung: Man wirft eine Exception, die mehrere andere Exceptions "zusammenfasst". In Einzelfall kommt es eben immer darauf an, WER die Kompetenz hat, einen aufgetretenen Fehler zu behandeln. Und wer auch immer diesen Fehler behandelt: Er tut es in einem try-catch-Block.

Dazu kommen noch einige Feinheiten - eine Websuche nach
"Checked Exceptions" "Unchecked Exceptions"
liefert da ggf. noch mehr infos.
 

GambaJo

Mitglied
Auf die Idee Usereingaben per exceptions zu prüfen, wäre ich nicht gekommen. Muss mir da noch ein paar Gedanken zu machen.

Das mit den Dateien habe ich auch schon gelesen.

Verstehe ich das richtig, dass man try/catch nur da nutzt, wo es zu erwarteten Komplikationen kommen kann, man aber im Code keinen Einfluss drauf hat?
 

musiKk

Top Contributor
Nun, ich wuerde Fehler nicht "erwarten", ich rechne mit ihnen. Oft gibst du ja das Ruder aus der Hand, z. B. wenn du Dateien schreibst oder ueber das Netz verschickst. Da kann es Millionen Moeglichkeiten geben, dass etwas schief geht: Platte voll, Plattencontroller stirbt, OS spinnt, Router stirbt, Putzfrau zieht Kabel vom Switch, ... Man hofft es nicht, aber man kann es auch nicht beeinflussen (in diesem Sinne also "Ja" auf deine Frage). Durch die entsprechende Exception wirst du darauf hingewiesen und kannst reagieren (und wenn es nur der Versuch ist, einen Log-Eintrag zu schreiben und dann das Programm zu beenden).
 

GambaJo

Mitglied
Ich hab da noch eine Frage zu "throws".

Ich habe für meine kleine Applikation einen DataAbstractionLayer geschrieben. Dieser ist für die eigentliche Kommunikation mit der Datenbank zuständig. Ziel war es eine Klasse zu erstellen, die ich auch für zukünftige Projekte nutzen könnte.

Die Applikation kennt nur meinen DataAbstractionLayer und seine Methoden. Nur der DataAbstractionLayer kennt die Methoden, die die eigentliche Datenbank-API zur Verfügung stellt.

Der DataAbstractionLayer enthält z.B. eine Methode, über die sich die Applikation mit der Datenbank verbinden kann. Die Methode der Datenbank kann eine eigene Exception werfen, wenn z.B. die Datenbank gesperrt ist.

Bisher habe ich das direkt in der Methode des DataAbstractionLayers abgefangen und einen Fehlercode zurück gegeben. Nun möchte ich das aber so machen, dass kein Fehlercode zurück gegeben wird, sondern die Exception an den Aufruffer weiter geben. Das bedeutet aber, dass der Aufrufer diese Art von Exception kennen müsste. Damit müsste ich die Datenbank-API der gesamten Applikation bekannt machen, was ich ja nicht will.

Zur Veranschaulichung die aktuelle Methode:

Code:
    public ObjectContainer connectToDataBase(String dbname) {
        setErrMsg("");//clear the error-message
        if (m_databaseName.isEmpty()) setDbName(dbname);
        
        //proof if databasename is empty
        if (m_databaseName.isEmpty()) {
            setErrMsg("No Database specified.");
            System.out.println(getErrMsg());
            return null;
        }
        
        ObjectContainer container = null;
        
        try {
            //open or create a databasefile
            container = Db4o.openFile(m_databaseName);
            
            //set the container
            setObjectContainer(container);
            
            //set the update-depth
            if(m_updateDepth > 0) container.ext().configure().updateDepth(m_updateDepth);
        } catch (Db4oException ex) {
            printException(ex);
            return null;
        }
        return container;
    }

Db4oException ist eine solche Exception. Wie kann ich das elegant lösen?
 

Murray

Top Contributor
Wenn Deine Exception keine "checked exception", sonderm eine "runtime exception" ist (wenn sie also nicht von java.lang.Exception, sondern von java.lang.RuntimeException erbt), dann muss der Verwender sie nicht unbedingt kennen, um die Methode zu benutzen.
 

GambaJo

Mitglied
Angenommen die Methode würde wie folgt aussehen:

Code:
public ObjectContainer connectToDataBase(String dbname) throws Db4oException {
...
}

Wie müsste konkret der Try-catch-Block des Aufrufers aussehen (wie gesagt, der Aufrufer kennt Db4oException nicht)?

Das habe ich aus der API:

com.db4o.ext
Class Db4oException

java.lang.Object
extended by java.lang.Throwable
extended by java.lang.Exception
extended by java.lang.RuntimeException
extended by com.db4o.foundation.ChainedRuntimeException
extended by com.db4o.ext.Db4oException

All Implemented Interfaces:
java.io.Serializable com.db4o.ext
Class Db4oException

java.lang.Object
extended by java.lang.Throwable
extended by java.lang.Exception
extended by java.lang.RuntimeException
extended by com.db4o.foundation.ChainedRuntimeException
extended by com.db4o.ext.Db4oException

All Implemented Interfaces:
java.io.Serializable
 

musiKk

Top Contributor
Die Exception erbt von RuntimeException, muss also nicht gefangen werden. Es gibt verschiedene Ansichten, wie man mit Exceptions umzugehen hat und eine davon sagt, dass man RuntimeExceptions auch nicht fangen sollte (vertrete ich zu einem gewissen Teil auch, aber nicht komplett). Wenn du diese hier dennoch fangen willst, kann jeder Typ ins catch, der auch in der Hierarchie ueber der Db4oException steht.

Wenn du die Exceptions, die dein DAL wirft von selbigem trennen willst, sodass der Aufrufer die in diesem Fall Db4oException nicht zu Gesicht bekommt, dann bietet es sich an, eine eigene Exception zu entwerfen. Das DAL faengt die Db4oException und wirft die eigene stattdessen. Da koenntest du den Fehlercode reinschreiben. Die Frage ist nur, wie sinnvoll das ist. Klar kann man argumentieren, dass man ueber einen Stacktrace Informationen leaken kann. Andererseits erschwert es das Debugging, weil im Fehlerfall an einem bestimmten Punkt halt schluss ist. Irgendwo fliegt eine Exception aus dem nirgendwo. Laesst sich natuerlich auch eingrenzen, wenn es entsprechend programmiert wird.
 

GambaJo

Mitglied
Ich hab das jetzt mal so umgeschrieben:

Methode aus dem DAL:

Code:
public void connectToDataBase(String dbname) throws Db4oException{
        setDbName(dbname);
        
        ObjectContainer container = null;

        //open or create a databasefile
        container = Db4o.openFile(m_databaseName);

        //set the container
        setObjectContainer(container);

        //set the update-depth
        if(m_updateDepth > 0) container.ext().configure().updateDepth(m_updateDepth);
    }

Und hier der Aufrufer:

Code:
private void formWindowOpened(java.awt.event.WindowEvent evt) {                                  
    //open database
    m_dal = new Db4oDataAbstractionLayer();
    if(m_dal == null) return;
    try{
        m_dal.connectToDataBase(DB_NAME);
    } catch (RuntimeException ex) {
        JOptionPane.showMessageDialog(this,ex.getMessage(),"Fehler",JOptionPane.OK_CANCEL_OPTION);
        this.dispose();
        return;
    }    
    setFirstColumnInvisible(jXTableRecipe);
    fillRecipeMainList();//fill list from database
    changeSelectionTableRecipe(0);//select the frist row
}

Hab dann testweise einen leeren Datenbanknamen übergeben, und bekam tatsächlich eine entsprechende Fehlermeldung. Das reicht ja so eigentlich, denke ich mal.
 

Marco13

Top Contributor
catch (RuntimeException ex)
ist eigentlich zu allgemein. Da werden auch Sachen gefangen, die nicht gefangen werden sollten. Der Aufrufer sollte die Db4oException kennen, oder du solltest in der connectToDataBase sowas machen wie
Code:
void connectToDataBase throws EineExceptionDieDerAufruferKennenDarf
{
    try
    {
         ....
    } 
    catch (Db4oException e)
    {
        throw new EineExceptionDieDerAufruferKennenDarf(e.getMessage());
    }
}
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
KogoroMori21 Wann ist der richtige Zeitpunkt, um sich Hilfe zu suchen? (Bin Informatik-Student) Java Basics - Anfänger-Themen 10
I Logik Zahlungsprozess - Wann Bestellobjekt anlegen? Java Basics - Anfänger-Themen 2
C Java Array Struktur, welche ist wann besser? Java Basics - Anfänger-Themen 12
berserkerdq2 Java streams, wann nutze ich ::, also 2x Doppelpuntk bei Streams? Java Basics - Anfänger-Themen 5
W Wann und warum hashcode und equals? Java Basics - Anfänger-Themen 14
W Wann Rückgabewerte 0, 1, -1? Java Basics - Anfänger-Themen 27
berserkerdq2 Wann soll ich den Stream schließen, wenn ich das in einer Methode habe? Java Basics - Anfänger-Themen 8
K In andere Zahlensysteme umwandeln, wann klappt immer der Trick mit log? Java Basics - Anfänger-Themen 6
W Zur Vererbung: Wann und wie? Java Basics - Anfänger-Themen 35
F Wann ist es eine Instanz und wann nicht? Java Basics - Anfänger-Themen 1
C Instanzen, wann muss ich Instanzen erzeugen & wo?) Java Basics - Anfänger-Themen 23
S Wann Methode abstract? Java Basics - Anfänger-Themen 10
S Wann buffer löschen? Java Basics - Anfänger-Themen 5
R Wie überprüfen wann der User online oder offline ist? Java Basics - Anfänger-Themen 5
C Polymorphie Was genau ist Polymorphie und wann genau sollte man es verwenden? Java Basics - Anfänger-Themen 9
I Wann ist Client plattformunabhängig? Java Basics - Anfänger-Themen 22
M Best Practice Wann eine Methode schreiben ? Java Basics - Anfänger-Themen 14
K Warum funktioniert das und wann erden die Objektmethoden nun ausgeführt? Java Basics - Anfänger-Themen 7
IngoF Welches Event kommt wann? Java Basics - Anfänger-Themen 8
M Wann eigene implementierte HashCode Methode zwingend erforderlich? Java Basics - Anfänger-Themen 1
X Wann schreibt man diese Syntax zeichen { } Java Basics - Anfänger-Themen 8
O Wann nutzt man static? Java Basics - Anfänger-Themen 19
C Klassendesign / Wann Interface implementieren und wann Klassen vererben? Java Basics - Anfänger-Themen 3
S Wann existiert eine Instanz (eigene Klasse) Java Basics - Anfänger-Themen 8
M Wann PATH und wann JAVA_HOME in Windows System 7 setzen? Java Basics - Anfänger-Themen 2
M Wann final verwenden? Java Basics - Anfänger-Themen 5
M Wann eine Wrapper Klasse verwenden und wann einen primitiven Datentypen? Java Basics - Anfänger-Themen 8
D Ab wann getter und setter Java Basics - Anfänger-Themen 2
B Erkennen, wann static oder nicht? Java Basics - Anfänger-Themen 7
E wann welche Konstanten verwenden? Java Basics - Anfänger-Themen 7
P Wann Byte-Stream und wann Character-Stream? Java Basics - Anfänger-Themen 11
T Vererbung Wann wird die Methode paint aufgerufen? Java Basics - Anfänger-Themen 4
M Wann statische Methoden/Attribute? Java Basics - Anfänger-Themen 2
vandread Java Wildcards - Wann super wann extends? Java Basics - Anfänger-Themen 2
K Wann Vererbung und wann Interface verwenden? Java Basics - Anfänger-Themen 12
D Wann genau nutze ich ein solches Interface? Java Basics - Anfänger-Themen 3
K Wann genau brauche ich die Anweisung gleich null? Java Basics - Anfänger-Themen 10
B Wann toString() überschreiben? Java Basics - Anfänger-Themen 21
S OOP Wann Proxies und Interfaces? Java Basics - Anfänger-Themen 3
P Threads Wann läuft es parallel ab ? Java Basics - Anfänger-Themen 4
C Variablen Wann werden Instanzvariablen initalisiert? Java Basics - Anfänger-Themen 10
P Java Stream, wann welche Stream verwenden? Java Basics - Anfänger-Themen 3
T Ab wann ist es ein großes Projekt? Java Basics - Anfänger-Themen 35
N Bessere Performance durch final: wann denn überhaupt? Java Basics - Anfänger-Themen 28
D Wann genau abstrakte Klasse und wann ein Interface verwenden? Java Basics - Anfänger-Themen 4
W Wann nutze ich "import"? Java Basics - Anfänger-Themen 12
A junit test wann verwendet man "was"? Java Basics - Anfänger-Themen 4
H Wann ein Objekt der Programmklasse in main anlegen Java Basics - Anfänger-Themen 2
G Wann ist ein == Vergleich bei Gleitkommazahlen fahrlässig? Java Basics - Anfänger-Themen 8
T Wann for und wann while?? Java Basics - Anfänger-Themen 35
-horn- Wann wird alles NaN erzeugt? Java Basics - Anfänger-Themen 22
S Wann wird eine Klasse geladen? Java Basics - Anfänger-Themen 17
C this - wann verwende ich das? Java Basics - Anfänger-Themen 10
T Threads - Ab wann wirds Kritisch?! Java Basics - Anfänger-Themen 7
M Wann muss man eine Variable mit set-/get-Methoden in eine Bean schreiben? Java Basics - Anfänger-Themen 19
G field public/private wann Java Basics - Anfänger-Themen 11
GambaJo Ab wann neue Klasse erzeugen? Java Basics - Anfänger-Themen 2
G Wann Arrays, wann Collections? Java Basics - Anfänger-Themen 36
B objekt wann als final deklarieren? Java Basics - Anfänger-Themen 2
N Wann muss eine Methode - protected sein wann public wann. Java Basics - Anfänger-Themen 5
Y Wann / Wozu inner class Java Basics - Anfänger-Themen 3
K StringBuilder notwendig ab wann? Java Basics - Anfänger-Themen 42
S wann static Funktionen wann nicht Java Basics - Anfänger-Themen 6
N Wann und wie oft finalize Methode verwenden( überschreiben ) Java Basics - Anfänger-Themen 6
Bernasconi Programmierstil / Wann eine neue Datei? Java Basics - Anfänger-Themen 5
M wann, welche schleife Java Basics - Anfänger-Themen 3
M Ab wann ist die Datei sichtbar? Java Basics - Anfänger-Themen 3
G Herausfinden, wann mehrere Threads abgeschlossen sind Java Basics - Anfänger-Themen 3
G Überprüfen wann ein Dokument abläuft? Java Basics - Anfänger-Themen 3
N SAX, StAX, JDOM oder DOM , ab wann welches für XML Java Basics - Anfänger-Themen 14
M Wann ist ein Programm beendet? Java Basics - Anfänger-Themen 6
G Wann am besten getSize() aufrufen? Java Basics - Anfänger-Themen 6
I Festellen wann Methode in anderer Klasse fertig ist Java Basics - Anfänger-Themen 5
M wann statische klassen? Java Basics - Anfänger-Themen 14
M Wann ist initialisieren sinnvoll? Java Basics - Anfänger-Themen 4
B Wann Comparator und wann Comparable Java Basics - Anfänger-Themen 6
R Wann benutzt man << oder >> ? Java Basics - Anfänger-Themen 2
G Klassen: Wann initialisiere ich wo meine Variabeln Java Basics - Anfänger-Themen 6
T catch(InputMismatchException) wird nicht ausgefürt/erkannt Java Basics - Anfänger-Themen 12
missy72 Catch Blöcke zusammenfassen Java Basics - Anfänger-Themen 6
Ostkreuz wie geht der catch? Java Basics - Anfänger-Themen 3
D try/catch-Block bei for-Schleife Java Basics - Anfänger-Themen 14
D Best Practice Ausgabe über direkte Ausgabe oder try-catch? Java Basics - Anfänger-Themen 13
districon Try - Catch Java Basics - Anfänger-Themen 8
JavaNoobi Try and Catch und übergabe von Objekten Java Basics - Anfänger-Themen 2
Y Wie kann ich die Variable in der Try Catch returnen? Java Basics - Anfänger-Themen 3
B Try-Catch Block Java Basics - Anfänger-Themen 3
B JUnit / Exceptions/ try-catch Java Basics - Anfänger-Themen 6
B try catch finally Java Basics - Anfänger-Themen 2
F Mehrere Exceptions in einem Catch-Block abfangen Java Basics - Anfänger-Themen 12
H throws und try catch Java Basics - Anfänger-Themen 8
H Try Catch Throw Exception Java Basics - Anfänger-Themen 1
S Try-Catch in Verwendung einer while Schleife Java Basics - Anfänger-Themen 2
I Try-Catch innerhalb eines Catchblocks Java Basics - Anfänger-Themen 1
J Endlosschleife bei Try-Catch? Java Basics - Anfänger-Themen 3
K JOptionPane/catch/try/finally/if Java Basics - Anfänger-Themen 9
V InputMismatchException (Try and catch) Java Basics - Anfänger-Themen 10
L do-while-Schleife läuft doppelt, try catch fehler Java Basics - Anfänger-Themen 12
J Erste Schritte catch Exeption Parameter Java Basics - Anfänger-Themen 7
TheMenox Try and Catch Java Basics - Anfänger-Themen 12

Ähnliche Java Themen

Neue Themen


Oben