2015-04-07 22 views
5

Quando la gestione degli errori in Java è comune vedere le superclassi essendo gli errori che sono Caugh, comeGestione di diverse eccezioni dello stesso tipo in Java?

Exception, IOException, SocketException, etc. 

Tuttavia come si fa a trovare i dettagli essenziali sul l'eccezione? Come si fa a selezionare una determinata eccezione dagli altri. Ad esempio, attualmente sto lavorando a un piccolo progetto utilizzando Netty.io che genera un'eccezione IOException per ogni tipo di errore di lettura/scrittura che è possibile assegnare. Questo ha senso, perché alla fine si tratta di errori di input/output, ma come gestirli singolarmente.

eccezioni Esempio:

java.io.IOException: An existing connection was forcibly closed by the remote host 
java.io.IOException: Connection reset by peer 
java.io.IOException: Stream closed 

la lista continua solo ad andare avanti, ma come si va sulla gestione di questi separatamente, un approccio che ho trovato mentre guardando in giro e sembra davvero brutto è la seguente.

try { 
    // ... 
} catch (IOException e) { 
    if(e.getMessage().contains("An existing connection was forcibly closed by the remote host")) { 
     // Handle error 
    } else //... 
} 

Questo sembra molto noioso e non è destinato ad essere un modo migliore per fare questo, un modo correct se si vuole. Ho esaminato un bel po 'di errori nella gestione delle annotazioni nelle ultime ore e tutti parlano solo dei ragazzini che vengono usati comunemente. IOException, Exception, SocketException, NullPointerException, and FileNotFoundException. Dove credo che SocketException e FileNotFoundException siano direttamente correlati allo IOException, più che probabile una sottoclasse, correggimi se sbaglio.

In ogni caso, qual è il modo corretto per gestire queste eccezioni e come si individua esattamente quale tipo di eccezione è necessario gestire? Tutto quello che posso veramente fare è gestire IOException fino a quando qualcosa di più preciso si presenta, ma quando si sviluppano applicazioni è sempre bene essere in grado di gestire ogni errore in modo univoco.

+0

Quando lo sviluppo di applicazioni, si dovrebbe incapsulare le eccezioni che meritano di essere gestita in modo diverso come eccezioni di tipo diverso. Quindi non è necessario gestire i loro messaggi per conoscere le specialità. –

+0

Poiché la libreria utilizzata usa solo 'IOException' con messaggi diversi, il confronto delle stringhe è l'unico modo per distinguere. Sei sicuro di poter e gestire i diversi casi in modo diverso? In pratica ho scoperto che raramente si gestiscono correttamente le eccezioni individuali, quindi questo problema viene evitato trattando tutte le eccezioni simili allo stesso modo. – Richard

+0

@Richard La libreria può essere stata * dichiarata * solo per generare "IOException", ma ciò non significa che non possa generare eccezioni derivate. Dovresti sperimentare. – EJP

risposta

2

Nella maggior parte di questi casi il messaggio è irrilevante dal punto di vista del codice. È solo qualcosa da mostrare all'utente, o registrato. L'unico dato saliente è che la connessione è interrotta, per qualsiasi motivo, e non ci sono percorsi di codice diversi che è possibile utilizzare a seconda del messaggio che è stato.

L'unico che è diverso è 'socket chiuso', che indica un bug di codifica.

EDIT Per quanto riguarda i vostri commenti qui sotto:

  • Qualsiasi IOException diverso SocketTimeoutException su un socket è fatale per la connessione.
  • pacchetti non validi non causano IOException: questo è un problema di livello di applicazione che genera eccezioni a livello di applicazione, o sottoclassi di IOException: esempio, java.io.StreamCorruptedException.
  • Non esiste una cosa come IOException: connection closed by remote host. Se il peer chiude la connessione, che provoca una condizione di fine del flusso, che si manifesta sia come read() ritorno -1, readLine() ritorni null, o readXXX() gettando EOFException per qualsiasi altra X.
+1

Quindi, il messaggio lanciato dall'eccezione è completamente irrilevante per la logica che il codice dovrebbe gestire? Non sarei d'accordo quando scrivo le applicazioni del server. Ad esempio, se IOException si è lamentato delle lunghezze dei pacchetti non valide rispetto a una disconnessione di un utente. Forse quando l'utente viene disconnesso a causa di un determinato evento, si desidera memorizzare nella cache i propri dati in memoria in modo che possano effettuare il back-back online in modo rapido ed efficiente senza caricare nuovamente tutti i dati utente dal database. Potrei sbagliarmi, ancora cercando di capire meglio questo. – Hobbyist

+0

Sembra proprio che se l'utente si disconnette a causa di un problema di rete, piuttosto che l'utente che si disconnette (che lancia il messaggio "Connessione chiusa tramite host remoto"), è possibile seguire un altro processo. – Hobbyist

+3

@ Christian.tucker Sembra che tu lo stia complicando eccessivamente. È molto raro (non impossibile, solo raro) che tu debba sapere quale sia il messaggio nel tuo codice per qualsiasi eccezione. Questo è l'intero punto di tipizzazione delle eccezioni. Per tutti i casi d'angolo che hai elencato, ti consiglierei una singola serie di azioni (ad esempio: salvare lo stato utente in caso di disconnessione in QUALSIASI caso). – MadConan

1

suggerirei cattura le eccezioni in ordine, dal più specifico al meno - in modo tale che noterai un pattern di interruzione di circuito quando viene raggiunta l'eccezione che stai cercando.Questo è il meglio che posso venire con:

try { 
    /// Something that can result in IOException or a SocketException 
catch (IOException e){ 
    //Do something specific 
}catch (SocketExcpetion e){ 

}catch (Exception e) { //or some superclass of the above exceptions 
/// 
} 

Non dimenticare che si può anche prendere più eccezioni di tipo diverso con il comando |: catch (IOException|SocketException|

+0

Grazie per il suggerimento, ma il punto centrale della domanda era trovare il tipo specifico di eccezione, ad esempio 'IOException estende Exception' e' FileNotFoundException estende IOException' – Hobbyist

+2

@ Christian.tucker Non sono sicuro se capisco il tuo commento. Nella tua domanda sembri pretendere (a meno che non lo miseria) che ti trovi di fronte a situazioni in cui ottieni esattamente IOExcepption non una sottoclasse particolare come 'FileNotFoundException' e che devi gestirli in base al contenuto del messaggio. Ma nei tuoi commenti affermi che "il punto della domanda era trovare il tipo specifico di eccezione, ad esempio IOException estende Exception e FileNotFoundException estende IOException". Quindi ottieni un tipo preciso (FileNotFoundException) o no (IOException)? – Pshemo

+1

@ Christian.tucker o stiamo parlando di situazione in cui è dichiarato che il metodo genera solo IOException in modo che il compilatore ti aiuti a gestirlo, ma in realtà il metodo può generare FileNotFoundException? In tal caso è sufficiente posizionare il caso per 'FileNotFoundException' prima che la gestione del caso' IOException' risolva il problema. – Pshemo

1

La documentazione (http://docs.oracle.com/javase/7/docs/api/java/io/IOException.html) contiene una lunga lista di sottoclassi dirette. Potresti volerli esaminare e controllare quali vuoi trattare in modo diverso. Una volta che sai che, è possibile utilizzare più di cattura-blocchi, prima le sottoclassi, allora l'IOException più generale:

catch(SSLException se) { 
    // do something 
} 
catch(HttpRetryException he) { 
    // do something else 
} 
catch(IOException ioe) { 
    // nop 
}