2012-09-24 19 views
24

In der Vergangenheit „Throwable wirft“ Ich Tonnen Code mit Methoden wie gelesen hatte:ist eine gute Praxis

public Object doSomething() throws Throwable { 
    ... 
} 

ist es üblich, das zu tun?

Was sind Profis? & Nachteile?

Ist es nicht besser zu catch und printStackTrace()?

throws Trowable schien mir wie der "Agent Orange" Art und Weise der Ausnahme- Materie

getan des Erhaltens

EDIT


  1. Handle erwartet Ausnahmen in der Methode

  2. Werfen unexpectet (eins nach dem anderen)

  3. Nicht programmatische Pflege eines Fehlers

Ist das der Weg zu gehen?

+1

wahrscheinlich wird dies Ihnen eine Erklärung geben: http://StackOverflow.com/Questions/498217/When-Should-Throwable-be-used-instead-of-new-Exception – Serge

+0

"Throws Throwable" ist häufiger in SDKs und Framework-Definitionen. Hier ist ein Beispiel im Android-Test-Framework, in dem sie es verwenden: http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4.2_r1/android/test/ InstrumentationTestCase.java # InstrumentationTestCase –

Antwort

42

Sie sollten Throwable nicht werfen. Hier ist der Grund.

Throwable ist die Spitze der Hierarchie der Dinge, die geworfen werden können und besteht aus Exceptions und Errors. Da Errors per definitionem aus unsauberen Bedingungen entstehen, ist es sinnlos, sie in Ihre Methodendeklaration aufzunehmen. Das lässt nur Exception.

Sie sollten Ihre Methode stattdessen mit throws Exception deklarieren.


Beachten Sie, dass je enger der Bereich throws desto besser.

Die Angabe der Methode throws Exception ist in Ordnung, wenn Ihre Methode die Ausnahmen nicht generiert, sondern anderen Code aufruft, der als throws Exception deklariert ist und Sie Ausnahmen zum Perculate des Aufruf-Stacks benötigen.

Wenn Ihre Methode die ist die Ausnahme zu erzeugen, erklären dann einen engeren Bereich, zB throws IOException, MyProcessingException, etc

+2

Ich würde hinzufügen, dass, wenn die Ausnahmen, die Sie sammeln, durch Code an irgendeinem Punkt in der Kette korrigiert werden kann, dann ist es in Ordnung zu deklarieren Gibt Exception() aus, aber wenn es nicht vom Code verwendet wird, um sich selbst zu reparieren, sollten Sie die Exceptions abfangen und als RuntimeExceptions erneut werfen. In diesem Fall deklarieren Sie in Ihrer Methode nicht, dass eine Runtime-Ausnahme ausgelöst wird. Stattdessen dokumentieren Sie, dass dies mit javadoc geschieht. –

1

Funktional ist es äquivalent mit throws Exception, da Fehler deaktiviert sind.

Ich sehe keinen Grund, eine Methode zum Werfen Throwable zu deklarieren. Dies bedeutet jedoch nicht, dass catch und printStackTrace eine gute Alternative sind.

Normalerweise möchten Sie throwables fangen, wo Sie etwas Sinnvolles mit ihnen tun können.

Code, der einen Wurf wirft, den Sie nicht erwarten, sollte herrlich explodieren, damit Sie den Fehler sehen und den Fehler beheben können.

+2

Sie können eine Unterklasse von Throwable werfen, die keine Ausnahme oder ein Fehler ist, aber dies wird nicht empfohlen. ;) –

+0

Korrekt natürlich. Ich hoffe wirklich, dass das in der Praxis nicht von Bedeutung sein wird. – Buhb

+1

Unterklassen von Throwable werden wie Throwable überprüft (außer Unterklassen von Error und RuntimeException) –

0

Fragen Sie gezielt nach Throwable? Wenn ja, dann ist es keine gute Übung. Es bietet dem Klassenbenutzer (Methode) keine nützlichen Informationen.

1

Ist es üblich, dies zu tun?

Im JDK ist es selten. Dies wird hauptsächlich verwendet, wenn nicht klar ist, wie mit geprüften Ausnahmen verfahren werden soll.

Was sind Profis? & Nachteile?

Die Profis ist, dass Sie Ihren Code zu überprüfen exception.s, ohne sich Gedanken

Die Nachteile zu kompilieren erhalten, ist diese Ausnahme Sie ignoriert werden sollten Handhabung.

Ist es nicht besser, StackTrace() zu fangen und zu drucken?

Unbehandelte Ausnahme werden normalerweise sowieso gedruckt, so dass sie nicht viel hilft.

Sie sollten eine Ausnahme abfangen, wenn Sie einen Wert hinzufügen können, und die Ausnahme zur Klausel throws hinzufügen, wenn dies nicht möglich ist.

8

, die die geladene Frage ist. Hier geht es weniger um die Ausnahmebehandlung als um die Lesbarkeit von Code.

Es hängt davon ab, wo Sie Ihre Code-Beispiele erhalten. Fachleute ziehen es vor, spezifischer zu sein, wenn sie eine Methode auswerfen. Der Hauptgrund ist, dass es Ihre APIs lesbarer hält. Wenn Ihre Methode zum Beispiel "Throwable" auslöst, bedeutet das grundsätzlich, dass alles passieren kann und Ihre Methode nicht damit umgehen will. Aber wirklich, nur eine begrenzte Anzahl von Dingen passieren könnte:

  • Was auch immer Ausnahmen geprüft aus anderen Anrufe, die Sie in Ihrer Methode machen
  • Was auch immer Ausnahmen geprüft Sie absichtlich werfen auf der Grundlage Ihrer eigenen Behauptungen
  • Was auch immer ungeprüfte Ausnahme Sie nicht planen für
  • Fehler (java.lang.Error), die mehr global für die JVM und die Umwelt

Durch die gezielte sta Wenn Sie die Ausnahmen eingeben, die Sie auslösen möchten, teilen Sie den Benutzern Ihrer API mit, was sie beachten sollten. Zum Beispiel, wenn Sie InputStream verwenden, werden Sie bemerken, dass die meisten Methoden mindestens java.io.IOException werfen, was Ihnen einige nützliche Informationen darüber gibt, worauf Sie achten sollten.

Beim Codieren möchten Sie in der Regel versuchen, Ihre APIs so ausdrucksstark wie möglich zu halten. Sie haben im Wesentlichen eine Codezeile, um die öffentliche API einer Methode zu zeigen (d. H. Ihre Signatur, auch Anmerkungen, ich denke), also wollen Sie sie vollständig ausdrücken (Rückgabetyp, Name, Parameter, aber auch die geworfenen Ausnahmen).

Soweit ich die Throwables erfassen und den Stack-Trace drucken würde, würde ich sagen, dass Sie die Ausnahme nicht abfangen sollten, wenn Sie nichts dagegen tun können.Lassen Sie es stattdessen den Aufruf-Stack aufrollen, bis eine Klasse es fängt, etwas dagegen zu tun. Manchmal kann es bis zu Ihrer Hauptklasse hochrollen, was ich denke, dass Sie es abfangen und den Stack-Trace als letzten Ausweg drucken müssen. Grundsätzlich, wenn Sie nicht auf die Ausnahme reagieren können, dann lassen Sie es den Call-Stack gehen. Es ist auch extrem selten, dass Sie sich in einer Situation befinden, in der Sie eine Ausnahme zum Schweigen bringen sollten (d. H. Fangen Sie sie aber tun Sie nichts dagegen). Dies führt normalerweise zu Problemen, wenn Probleme behoben werden müssen.

Hier ist ein Spaß, aber interessant article um Missbrauch der Ausnahme Handhabung im Allgemeinen.

1

Es ist wirklich umstritten. Wenn die Methode zu viele Ausnahmen auslöst, führt dies zu einer Menge Code zur Fehlerbehandlung. Manchmal ist es nicht beabsichtigt.

Aber weil ich nicht zu viele Ausnahmen in der Signatur mag, bedeutet nicht, dass wir Eltern aller Ausnahmen verwenden und wir sind fertig !! Es wird nicht funktionieren.

Was man tun kann, ist Ausnahmen zu kategorisieren wie BusinessException, ServiceException so dass, wenn Sie eine Geschäftsregel, die besagt, dass minimum balance in account can not be less than say 100$ dann InsufficientBalance Ausnahme erzeugt wird, welche BusinessException

Kind sein wird, so dass Sie Methode wird wie

public Object doSomething() throws BusinessException { 

if(!hasMinimumbalance()) 
    { 
    throw new InsufficientBalance(ErrorCode); 
    } 
} 

Was dies tun wird ist Club verbunden Ausnahmen zusammen und wann immer API Benutzer möchte Ausnahme spezifische Fehler erkennen, dann kann er es tun, sonst generische Fehlerbehandlung möglich ist.

Der Kernpunkt ist hier auf der Benutzeroberfläche Sie dem Benutzer angezeigt werden soll, die Sie haben aus dem Gleichgewicht laufen und Sie können kein Geld

Sie können auf den größeren Aspekt sagen entziehen Menschen lesbaren Form angezeigt werden von Fehler Es ist wirklich notwendig, Ausnahmen zu trennen.

0

Werfen (und fangen) Throwable (oder Exception) ist in der Regel eine schlechte Übung, da es bestimmte Ausnahmen "überdeckt", die Sie vielleicht fangen möchten. Dann würden Sie wie unten an Hässlichkeit zurückgreifen:

public void myMethod() throws Throwable { 
    if (x) { 
     throw new MyException1(); 
    } 
    if (y) { 
     throw new MyException2(); 
    } 
} 

public void callingMethod() { 
    try { 
     myMethod(); 
    } 
    catch(Throwable t) { 
     if (t instanceof MyException1) { 
      // handle exception 1 
     } 
     else if (t instanceof MyException2) { 
      // handle exception 2 
     } 
     else { 
      // handle other exceptions 
     } 
    } 
} 

Welche ist fehleranfällig (und durch Check als Codeverletzung markiert). Es ist viel preferrable Code wie diese zu haben:

public void myMethod() throws MyException1, MyException2 { 
    if (x) { 
     throw new MyException1(); 
    } 
    if (y) { 
     throw new MyException2(); 
    } 
} 

public void callingMethod() { 
    try { 
     myMethod(); 
    } 
    catch(MyException1 e) { 
     // handle exception 1 
    } 
    catch(MyException2 e) { 
     // handle exception 2 
    } 
} 

eine Ausnahmebehandlung nur durch den Aufruf von print() ist in der Regel keine gute Idee. printStackTrace() sendet den Stacktrace an den Standardfehler, der überhaupt nicht gelesen werden kann. Eine bessere Option ist die Protokollierung der Anwendung (wie log4j), um die Ausnahme zu melden. Selbst dann könnte es einfach nicht reichen, es einfach zu protokollieren.

Faust Meine Regel ist:

Wenn Sie eine Ausnahme lokal verarbeiten kann, so tun. Zum Beispiel, wenn das Parsen einen String als Integer Sie die Number fangen können und einen Standardwert zurück:

prvate int parseAmount(String amountValue) { 
    int amount; 
    try { 
     amount = Integer.parseInt(amountValue); 
    } 
    catch(NumberFormatException e) { 
     // default amount 
     amount = 0; 
    } 
    return amount; 
} 

Wenn Sie keine Ausnahme lokal verarbeiten können, sollten Sie, wenn Sie den Ausnahmetyp aussetzen sollten, die ausgelöst wird.Wenn diese Art einig obskurer (abhängig von der Implementierung) Typ ist, dann ist es in Ihrem eigenen generischen Ausnahmetyp Verpackung ist wahrscheinlich eine gute Idee:

private Customer getCustomer(int customerId) throws ServiceException { 
    try { 
     return customerService.getCustomer(customerId); 
    } 
    catch(CustomerServiceSpaghettiTangledException e) { 
     throw new ServiceException("Error calling the customer service", e); 
    } 
} 

Hier ServiceException 'ist eine Unterklasse von Exception von Euch erstellt. Frühling bietet auch eine exception hierarchy speziell für diesen Zweck.

Durch die Umgehung der Ausnahme verbergen Sie die Implementierungsdetails, wodurch Ihre Serviceebene wesentlich einfacher zu verwenden ist.

Wenn Sie entscheiden, eine Ausnahme von Ihrer Methode zu werfen, müssen Sie sie im Callstack "höher" behandeln. Dies kann eine generische Fehlerseite in Ihrer Webanwendung sein, die besagt, dass etwas schief gelaufen ist und möglicherweise eine Fehlermeldung oder einen Code enthält. In einigen Fällen kann der Code auf höherer Ebene einen erneuten Versuch oder möglicherweise einen alternativen Weg zum Erhalten des erforderlichen Ergebnisses versuchen.

1

In einigen seltenen Fällen ist es akzeptabel, Throwable s zu werfen. Zum Beispiel werden @Around Ratschläge in Spring AOP normalerweise als Throwable deklariert.

Das folgende Beispiel wird wörtlich aus Spring AOP docs kopiert:

import org.aspectj.lang.annotation.Aspect; 
    import org.aspectj.lang.annotation.Around; 
    import org.aspectj.lang.ProceedingJoinPoint; 

    @Aspect 
    public class AroundExample { 

     @Around("com.xyz.myapp.SystemArchitecture.businessService()") 
     public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { 
      // start stopwatch 
      Object retVal = pjp.proceed(); 
      // stop stopwatch 
      return retVal; 
     } 

    } 

Warum erklärt doBasicProfiling eine Throwable zu werfen? Weil die ursprüngliche Methode (d. H. Der Ausführungsverknüpfungspunkt) eine Error, RuntimeException oder eine geprüfte Ausnahme auslösen kann. Es macht also nur Sinn, doBasicProfiling zu deklarieren, um eine Throwable zu werfen.

Verwandte Themen