2011-10-31 14 views
12

Perché è sconsigliato lanciare un'eccezione generica (java.lang.Exception), quando di solito è sufficiente per gestire la maggior parte dei fallimenti condizionali all'interno di un metodo? Capisco che se un metodo può lanciare più tipi di eccezioni, allora lanciare sottoclassi specifiche di un'eccezione potrebbe chiarire la gestione di un bit, ma in un caso di fail/fail generale penso che Exception sia più che adeguato.Eccezione generica di lancio scoraggiata?

+0

possibile duplicazione di [Best practice per la gestione delle eccezioni in Java o C#] (http://stackoverflow.com/questions/409563/best-practices-for-exception-management-in-java-or-c-sharp) –

risposta

20

Il problema è che Exception è anche la superclasse di RuntimeException, che comprende alcune cose che non dovrebbero essere prese in quanto indica un problema con la programmazione, piuttosto che un eccezionale condizione che deriva dal contesto. In circostanze normali, non si desidera rilevare BufferOverflowException o UnsupportedOperationException. Inoltre, il lancio di tipi di eccezioni separati fornisce al codice di chiamata il controllo su come gestirne ciascuno. Boilerplate è ridotto in Java 7 con la nuova funzionalità multi-catch.

+1

Questo è un altro problema importante, +1. –

+0

@MarkPeters Anche se raramente dico "mai", dal momento che anche il peggior anti-pattern può essere la risposta giusta in situazioni contorte, è meglio fare attenzione con le eccezioni. A volte devono essere gestiti da un codice che non hai scritto e finirai col perdere le astrazioni in tutto il negozio. Poi, naturalmente, c'è chi cattura "Throwable" come se non fosse un grosso problema: D –

+0

+1 - Punto davvero ottimo. – DerMike

5

Se si lanciano eccezioni più specifiche, ciò non impedisce a nessun codice chiamante di occuparsi di tutti in un blocco di cattura Exception. Essere più specifici è più documentare su quale tipo di errori si verificano, rendendo più facile per i programmatori gestirli separatamente.

Inoltre, lanciando "Exception" si sta dicendo ai chiamanti del codice che non possono escludere alcuna classe di eccezione. Un IOException potrebbero verificarsi, come potrebbe un NumberFormatException, ecc

1

In genere si desidera sapere cosa è successo nella propria app e si rilevano solo eccezioni specifiche e si lascia che il programma fallisca (o diventi più alto nell'ordine di esecuzione) quando si ottiene l'eccezione che non si targetizza in modo specifico. Catching Exception li catturerà tutti e in alcuni casi non sapresti che il tuo programma sta fallendo.

3

Come sempre: dipende.

Penso che ci sia una differenza tra API che esponi agli altri. Potrebbe vivere per qualche tempo. In tal caso non si conosce ciò che il chiamante ritiene migliore per il suo caso.

D'altra parte c'è sempre un codice che usi internamente solo per te stesso. Di quanto potrebbe essere sufficiente lanciare un'eccezione generica. Ma ricorda, potresti voler cambiare qualche gestione delle eccezioni in seguito. Ciò sarà più difficile quando tutti i casi di errore verranno distrutti insieme.

0

Dittos to GH. Avrei usato "eccezione puntatore nullo" e "eccezione memoria insufficiente" come esempi più ovvi del tipo di eccezioni che probabilmente non guardi nello stesso blocco con le eccezioni di vera applicazione.

Vorrei anche aggiungere che vale la pena fare un piccolo sforzo per l'espandibilità futura. Se si lanciano eccezioni generiche dappertutto e in seguito si decide che è necessario rilevare alcune eccezioni e non altre, può essere un grosso problema tornare indietro e modificarle tutte. Ma se crei le eccezioni di cui hai bisogno mentre vai avanti, non è un grosso problema. La creazione di una nuova classe di eccezioni che accetta solo un costruttore con un messaggio prende, quali, 5 linee di codice? È un buon investimento per il futuro.

Come molte cose in programmazione, è una questione di quanto lontano si va. Generalmente creo una "BadInputException" piuttosto generica in quasi tutti i progetti su cui lavoro, e lancio questo in qualsiasi momento in cui gli utenti immettono i criteri di convalida dei fallimenti. Quindi posso solo prendere BadInputException e lanciare il messaggio sullo schermo. Se creo una classe complessa che genera eccezioni per dati incoerenti e quel genere di cose, di solito creo una classe di eccezioni per questo. Come se creo una classe "TalkToDatabase", creerò un "TalkToDatabaseException". (Forse più di questo se ci sono più tipi di eccezioni che so di voler prendere, ma almeno quella.)

E a proposito, non so se ci stai pensando, ma sconsiglio vivamente di esaminare il testo di un messaggio di errore per determinare il tipo di errore. Ho visto programmi in cui si gettano eccezioni generici in tutto il luogo, e poi in blocchi catch hanno codice come

// Very bad idea! Don't do this! 
catch (Exception ex) 
{ 
    if (ex.getMessage().equals("Invalid foo")) 
    ... handle bad foo ... 
    else if (ex.getMessage().equals("Plugh is over maximum")) 
    ... handle bad plugh ... 
    ... etc ... 
} 

Sarebbe molto meglio fare solo eccezioni separate per questi casi. Non solo l'elaborazione sarà molto più efficiente, ma supponiamo che tu faccia quanto sopra e che qualcuno arrivi più tardi e decida di cambiare il messaggio in "Foo is invalid"? Il programma verrà comunque compilato, ma non funzionerà correttamente.

Problemi correlati