2009-01-31 12 views
37

Dato: Throwable è la superclasse di eccezione.Quando è possibile utilizzare Throwable anziché la nuova eccezione?

Quando ho letto testi di scrivere i propri 'eccezioni', vedo esempi di Throwable utilizzati nel blocco catch e altri testi mostrano new Exception() utilizzato nel blocco catch. Devo ancora vedere una spiegazione di quando uno dovrebbe usare ciascuno.

La mia domanda è questa, quando deve essere utilizzato Throwable e quando deve essere utilizzato new Exception()?

EDIT: All'interno del blocco catch o else utilizzando:

throw throwable; 

o

throw new Exception(); 
+1

Perché usate "nuovo"? Stai confrontando il pescato (lanciabile) contro il fermo (eccezione)? –

+0

@WolfmanDragon: Quindi stai lanciando Throwable/Exception da * inside * al blocco catch? Dobbiamo supporre che "throwable" sia un Throwable esistente catturato da quel blocco? –

+0

@Zach Scrivena: no, questa era una domanda generale. Ho scritto eccezioni in C++ ma mai in Java, e sono un po 'confuso. Il problema che ha sollevato questa questione è che ho bisogno di passare un''eccezione 'a un pezzo di codice che un collaboratore sta costruendo se una raccolta non viene costruita. – WolfmanDragon

risposta

11

(dai commenti) La questione che ha portato questo in su è che ho bisogno di passare un 'eccezione' per un pezzo di codice un collega sta costruendo se una raccolta non viene costruito.

In questo caso, si potrebbe desiderare di gettare un verificata un'eccezione. È possibile lanciare un Exception, una sottoclasse esistente appropriata (eccetto RuntimeException e le sottoclassi che sono deselezionate) o una sottoclasse personalizzata di Exception (ad esempio "CollectionBuildException"). Vedi lo Java Tutorial on Exceptions per essere aggiornato con le eccezioni Java.

+0

Mentre la tua risposta risponde al mio commento, continuo a non capire perché alcuni dei grandi nomi del settore dicono di lanciare Throwable (Hardcore Java di Robert Simmons, Jr.) mentre altri dicono di non usare Throwable. Hardcore Java sembra essere il libro jess besst di sempre, tranne in questo caso. – WolfmanDragon

+3

Throwable è la superclasse di Eccezioni ed errori. Delle tre classi, considererei Eccezione la più adatta per l'attività. La maggior parte delle persone scrive blocchi try-catch che si rivolgono solo a Exception e alle sue sottoclassi; non saranno in grado di gestire un nuovo Throwable(). –

+0

(continua) a meno che non ci sia un "catch (Throwable t)" anche. –

32

gettare sempre un'eccezione (mai un Throwable). In genere non prendi Throwable, ma puoi farlo. Throwable è la superclasse di Exception ed Error, quindi potresti prendere Throwable se vuoi non solo catturare Eccezioni ma Errori, questo è il punto di averlo. Il fatto è che gli errori sono generalmente cose che una normale applicazione non dovrebbe e non dovrebbe catturare, quindi usa Eccezione a meno che tu non abbia una ragione specifica per usare Throwable.

+6

Non lanciare eccezioni, lanciare la sottoclasse Exception appropriata o la propria. L'intero punto di Eccezione con sottoclassi è che diversi tipi di problemi possono avere le proprie eccezioni. Oltre ad includere il messaggio ed eventualmente avvolgere l'eccezione causa, è possibile aggiungere "dati" extra. –

+0

Sì, questo è quello che intendevo, lanciare una sottoclasse di Exception. Scusa, non stavo pensando abbastanza. –

+1

questa è la risposta corretta. il richiedente ha fatto una scelta sfortunata per la quale correggere. vedi anche il commento di cHao su una risposta diversa sopra la quale si abbina bene a questa. – necromancer

1

Throwable è un'interfaccia, non una classe. Due classi estendono Throwable, Exception ed Error.

La regola è: essere il più specifici possibile quando si rilevano le eccezioni: ciò significa, ad esempio, intercettare Eccezione anziché Throwable e IOException anziché Exception.

Non rilevare errori: gli errori sono errori. Risolvi il codice invece.

Se devi prendere assolutamente tutto, usa "prendi Throwable", ma questa è una cattiva forma.

+0

Anche Throwable è una classe concreta. –

+0

Ehi, in realtà avevo l'impressione che Throwable fosse un'interfaccia finché non ho guardato. Non so perché questo sia o se questa è una cosa nuova. –

+0

Grazie per averlo sottolineato - Immagino di essere stato fuorviato dal suffisso -able. –

7

Non si dovrebbe catturare un'eccezione e lanciarne una nuova come generale come "nuova eccezione".

Invece, se si desidera bolla l'eccezione solo effettuare le seguenti operazioni:

try { 
    // Do some stuff here 
} 
catch (DivideByZeroException e) { 
    System.out.println("Can't divide by Zero!"); 
} 
catch (IndexOutOfRangeException e) { 
    // catch the exception 
    System.out.println("No matching element found."); 
} 
catch (Throwable e) { 
    throw e; // rethrow the exception/error that occurred 
} 

Non è buona pratica, credo, per intercettare un'eccezione e lanciare una nuova eccezione al posto di quello che era elevato al tuo blocco di codice, a meno che tu non sollevi un'utile eccezione personalizzata che fornisca un contesto sufficiente a eludere la causa dell'eccezione originale.

+0

Il tuo codice non è Java. – starblue

+2

Questo codice eliminerebbe le eccezioni DivideByZero e IndexOutOfRange. Registrare l'eccezione prima di lanciarlo è generalmente una cattiva idea. Se viene registrata un'eccezione, solitamente è meglio farlo al livello nello stack responsabile della reale gestione dell'errore, senza il re-lancio. – erickson

+2

Il codice è pensato per rispondere alla domanda dell'operatore. Le migliori pratiche che non influenzano la domanda dell'operatore sono fuori dalla portata di questa risposta. Voglio solo mostrare che è possibile risolvere i casi di eccezione, ma ripetere l'eccezione se si è verificata un'eccezione eccezionale. – MichaelD

0

Come ho sentito quando java è uscito per la prima volta, la teoria era che Throwable poteva essere utilizzato per il trasferimento del controllo in altri casi oltre alle eccezioni. Non l'ho mai visto usato in quel modo però (e probabilmente è una cosa molto buona).

Pertanto, è sufficiente rilevare l'eccezione (o, meglio ancora, un'eccezione più dettagliata).

0

Lanciabile si intende catturato solo dal contenitore o dal ciclo principale del programma. La maggior parte delle volte cattura elementi al di sotto delle eccezioni, ad esempio l'errore non aggiunge molte funzionalità a un programma, dopotutto cosa è possibile fare se vengono lanciati altri errori di VirtualError. Non molto eccetto il log e continua.

+0

Quindi utilizzare il throwable se deve essere passato al main o al servlet per prendere una decisione logica? nuova eccezione() se è solo per essere registrato? – WolfmanDragon

1

throw new Exception(); è qualcosa che si dovrebbe mai fare in un blocco catch, ma potrebbe essere necessario o vuole fare un tiro new SomeException(throwable); (conservando la traccia stack completo), invece di throw throwable; al fine di conformarsi alle API del metodo, per esempio quando dichiara di lanciare SomeException ma stai chiamando il codice che potrebbe lanciare un IOException che non vuoi aggiungere alla clausola throws del metodo.

Il caso probabilmente più comune è new RuntimeException(throwable); per evitare di avere una clausola throws del tutto. Molte persone ti diranno che questo è un abuso orribile perché dovresti usare eccezioni controllate. IMO si sbagliano e le eccezioni controllate sono un errore nella progettazione del linguaggio Java che si traduce in un codice brutto e non gestibile.

+1

L'eccezione non controllata è una causa comune di "astrazione che perde". http://www.joelonsoftware.com/articles/LeakyAbstractions.html Sono perfette per la segnalazione di errori "taglia unica", utile in molti casi, ma non supportano la gestione delle eccezioni vera di fronte all'astrazione . – erickson

0

Tutte le eccezioni sono un problema alla fine ... anche dire che gli errori sono bug non significa nulla.

Gli errori non sono bug: si tratta di problemi riscontrati dalla VM host, ad esempio OutOfMemoryError. Le eccezioni sono un mezzo che l'operazione corrente può usare per notificare che non ha funzionato e forse fornire qualche diagnosi.

0

In generale, non si lancia o si prende Throwable. In particolare, gli errori JVM (che estendono Error()) non sono significa che devono essere catturati dal codice utente a meno che non si stia facendo un lavoro strano a livello di sistema.

Trattare "Throwable" come artefatto linguistico. La classe "Exception" è chiamata così perché è quella destinata ai programmatori quando vogliono che un blocco di codice esca "eccezionalmente" - non uscendo normalmente o restituendo un valore.

Ciò include sia situazioni di errore regolari (da "normale" intendo in contrapposizione agli errori JVM) sia luoghi in cui si utilizzano eccezioni come meccanismo di controllo.

0

Si consiglia di non utilizzare le eccezioni come un "tipo di ritorno" o ...

Se la condizione si sta gettando per è comune, si stanno spendendo una quantità enorme di risorse per tornare tale condizione alla chiamata routine. Le eccezioni sono costose da costruire.

Ho visto casi in cui i loop stretti che hanno generato eccezioni come "negativo" per es. Assegnazione di ID, questa routine occupava circa il 99% del tempo di CPU .. quando invece è stata modificata con una costante di ritorno documentata, questo è sceso al 25%.

5

solo due posti si dovrebbe vedere la parola Throwable in codice:

public static void main(String args[]) 
{ 
    try 
    { 
     // Do some stuff 
    } 
    catch(Throwable t) 
    { 

    } 
} 

E

public class SomeServlet extends HttpServlet 
{ 
     public void doPost(HttpRequest request, HttpResponse response) 
     { 
     try 
     { 
      // Do some stuff 
     } 
     catch (Throwable t) 
     { 
       // Log 
     } 
     } 
} 
+5

Anche questi due sarebbero almeno uno di troppo, IMO. Catturare 'Throwable' (specialmente al di fuori di' main') è una ricetta per il disastro, dato che stai gettando una rete troppo ampia. Più di semplici eccezioni a livello di app sono Throwable. Esempio comune: errori OOM. Come farai a registrarli, se l'atto stesso di scrivere un log provoca la creazione di un oggetto (leggi: assegnato, dal processo stesso che ha appena fallito)? E quando quello * non * fallisce, e adesso? Hai perso le informazioni che hanno causato l'errore originale, perché ne hai causato uno nuovo che verrà propagato. Questo è se l'app non muore. – cHao

Problemi correlati