Come gestire le eccezioni Java nel modo giusto

Come gestire le eccezioni Java nel modo giusto

Come principiante della programmazione, il concetto di la gestione delle eccezioni può essere difficile avvolgere la testa. Non che il concetto in sé sia ​​difficile, ma la terminologia può farlo sembrare più avanzato di quanto non sia. Ed è una caratteristica così potente che è soggetta a uso improprio e abuso.





In questo articolo imparerai cosa sono le eccezioni, perché sono importanti, come usarle e gli errori comuni da evitare. La maggior parte dei linguaggi moderni ha un qualche tipo di gestione delle eccezioni, quindi se passi da Java , puoi portare con te la maggior parte di questi suggerimenti.





Comprensione delle eccezioni Java

In Java, an eccezione è un oggetto che indica che si è verificato qualcosa di anomalo (o 'eccezionale') durante l'esecuzione dell'applicazione. Tali eccezioni sono gettato , che sostanzialmente significa che viene creato un oggetto eccezione (in modo simile a come vengono 'sollevati' gli errori).





Il bello è che puoi catturare eccezioni generate, che ti consentono di gestire la condizione anormale e consentire all'applicazione di continuare a funzionare come se nulla fosse andato storto. Ad esempio, mentre un puntatore nullo in C potrebbe bloccare la tua applicazione, Java ti consente di lanciare e catturare

NullPointerException

s prima che una variabile nulla abbia la possibilità di causare un arresto anomalo.



Ricorda, un'eccezione è solo un oggetto, ma con una caratteristica importante: deve essere esteso dal

Exception

classe o qualsiasi sottoclasse di





Exception

. Sebbene Java abbia tutti i tipi di eccezioni integrate, puoi anche crearne di tue se lo desideri. Alcuni dei eccezioni Java più comuni includere:

  • NullPointerException
  • NumberFormatException
  • IllegalArgumentException
  • RuntimeException
  • IllegalStateException

Quindi cosa succede quando si lancia un'eccezione?





Innanzitutto, Java cerca nel metodo immediato per vedere se c'è codice che gestisce il tipo di eccezione che hai lanciato. Se un gestore non esiste, esamina il metodo che ha chiamato il metodo corrente per vedere se esiste un handle. In caso contrario, esamina il metodo che ha chiamato Quello metodo, quindi il metodo successivo, ecc. Se l'eccezione non viene rilevata, l'applicazione stampa un'analisi dello stack e quindi si arresta in modo anomalo. (In realtà è più sfumato del semplice arresto anomalo, ma questo è un argomento avanzato oltre lo scopo di questo articolo.)

A traccia dello stack è un elenco di tutti i metodi che Java ha attraversato durante la ricerca di un gestore di eccezioni. Ecco come appare una traccia dello stack:

Exception in thread 'main' java.lang.NullPointerException
at com.example.myproject.Book.getTitle(Book.java:16)
at com.example.myproject.Author.getBookTitles(Author.java:25)
at com.example.myproject.Bootstrap.main(Bootstrap.java:14)

Possiamo ricavare molto da questo. Innanzitutto, l'eccezione generata era a

NullPointerException

. Si è verificato nel

getTitle()

metodo sulla riga 16 di Book.java. Quel metodo è stato chiamato da

getBookTitles()

sulla riga 25 di Author.java. Quella metodo è stato chiamato da

main()

sulla riga 14 di Bootstrap.java. Come puoi vedere, conoscere tutto questo semplifica il debug.

Ma ancora una volta, il vero vantaggio delle eccezioni è che puoi 'gestire' la condizione anormale catturando l'eccezione, sistemando le cose e riprendendo l'applicazione senza che si blocchi.

Utilizzo delle eccezioni Java nel codice

Diciamo che hai

someMethod()

che prende un numero intero ed esegue una logica che potrebbe interrompersi se l'intero è minore di 0 o maggiore di 100. Questo potrebbe essere un buon posto per lanciare un'eccezione:

come faccio a vedere chi mi ha bloccato su facebook
public void someMethod(int value) {
if (value 100) {
throw new
IllegalArgumentException

Per rilevare questa eccezione, devi andare dove

someMethod()

si chiama e usa il blocco try-catch :

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
}
// ...
}

Tutto all'interno del Tentativo block verrà eseguito in ordine fino a quando non viene generata un'eccezione. Non appena viene generata un'eccezione, tutte le istruzioni successive vengono ignorate e la logica dell'applicazione passa immediatamente a catturare bloccare.

Nel nostro esempio, inseriamo il blocco try e chiamiamo immediatamente

someMethod()

. Poiché 200 non è compreso tra 0 e 100, an

IllegalArgumentException

viene lanciato. Questo termina immediatamente l'esecuzione di

someMethod()

, salta il resto della logica nel blocco try (

someOtherMethod()

non viene mai chiamato) e riprende l'esecuzione all'interno del blocco catch.

Cosa succederebbe se chiamassimo

someMethod(50)

Invece? Il

IllegalArgumentException

non verrebbe mai lanciato.

someMethod()

verrebbe eseguito normalmente. Il blocco try verrebbe eseguito normalmente, chiamando

someOtherMethod()

quando someMethod() viene completato. quando

someOtherMethod()

termina, il blocco catch verrebbe saltato e

callingMethod()

continuerebbe.

Nota che puoi avere più blocchi catch per blocco try:

public void callingMethod() {
try {
someMethod(200);
someOtherMethod();
} catch (IllegalArgumentException e) {
// handle the exception in here
} catch (NullPointerException e) {
// handle the exception in here
}
// ...
}

Si noti inoltre che un optional finalmente esiste anche il blocco:

public void method() {
try {
// ...
} catch (Exception e) {
// ...
} finally {
// ...
}
}

Il codice all'interno di un blocco finalmente è sempre eseguito qualunque cosa accada. Se hai un'istruzione return nel blocco try, il blocco last viene eseguito prima di uscire dal metodo. Se si genera un'altra eccezione nel blocco catch, il blocco final viene eseguito prima che venga generata l'eccezione.

Dovresti usare il blocco final quando hai oggetti che devono essere ripuliti prima che il metodo termini. Ad esempio, se hai aperto un file nel blocco try e in seguito hai generato un'eccezione, il blocco finalmente ti consente di chiudere il file prima di abbandonare il metodo.

Nota che puoi avere un blocco finalmente senza un blocco catch:

public void method() {
try {
// ...
} finally {
// ...
}
}

Ciò consente di eseguire qualsiasi operazione di pulizia necessaria consentendo alle eccezioni generate di propagare lo stack di invocazione del metodo (ovvero non si desidera gestire l'eccezione qui, ma è comunque necessario ripulire prima).

Eccezioni selezionate e non selezionate in Java

A differenza della maggior parte dei linguaggi, Java distingue tra eccezioni controllate e eccezioni non controllate (ad es. C# ha solo eccezioni non selezionate). Un'eccezione verificata dovere essere catturato nel metodo in cui viene generata l'eccezione, altrimenti il ​​codice non verrà compilato.

Per creare un'eccezione selezionata, estendere da

Exception

. Per creare un'eccezione non controllata, estendere da

RuntimeException

.

Qualsiasi metodo che genera un'eccezione controllata deve denotarlo nella firma del metodo utilizzando il simbolo getta parola chiave. Dal momento che Java è integrato

IOException

è un'eccezione verificata, il codice seguente non verrà compilato:

public void wontCompile() {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Devi prima dichiarare che genera un'eccezione controllata:

public void willCompile() throws IOException {
// ...
if (someCondition) {
throw new IOException();
}
// ...
}

Si noti che un metodo può essere dichiarato come generatrice di un'eccezione ma non genera mai effettivamente un'eccezione. Anche così, l'eccezione dovrà comunque essere rilevata, altrimenti il ​​codice non verrà compilato.

Quando dovresti usare le eccezioni selezionate o deselezionate?

La documentazione ufficiale di Java ha un pagina su questa domanda . Riassume la differenza con una succinta regola empirica: 'Se ci si può ragionevolmente aspettare che un cliente si riprenda da un'eccezione, rendila un'eccezione controllata. Se un client non può fare nulla per recuperare dall'eccezione, rendila un'eccezione non controllata.'

Ma questa linea guida potrebbe essere obsoleta. Da un lato, le eccezioni controllate producono un codice più robusto. D'altra parte, nessun altro linguaggio ha controllato le eccezioni allo stesso modo di Java, il che mostra due cose: uno, la funzione non è abbastanza utile per essere rubata da altri linguaggi, e due, puoi assolutamente vivere senza di loro. Inoltre, le eccezioni controllate non funzionano bene con le espressioni lambda introdotte in Java 8.

Linee guida per l'utilizzo delle eccezioni Java

Le eccezioni sono utili ma facilmente abusate e abusate. Ecco alcuni suggerimenti e best practice per aiutarti a evitare di rovinarli.

  • Preferisci le eccezioni specifiche alle eccezioni generali. Usa |_+_| oltre |_+_| quando possibile, altrimenti usa |_+_| oltre |_+_| quando possibile.
  • Non prendere mai |_+_| ! Il |_+_| la classe si estende effettivamente |_+_| , e il blocco catch funziona effettivamente con |_+_| o qualsiasi classe che estenda Throwable. Tuttavia, il |_+_| la classe estende anche |_+_| , e non vorrai mai prendere un |_+_| perché |_+_| s indicano gravi problemi irreversibili.
  • Non prendere mai |_+_| ! |_+_| estende |_+_| , quindi qualsiasi blocco che cattura |_+_| catturerà anche |_+_| , e questa è un'eccezione molto importante con cui non vuoi scherzare (specialmente nelle applicazioni multi-thread) a meno che tu non sappia cosa stai facendo. Se invece non sai quale eccezione catturare, considera di non catturare nulla.
  • Usa messaggi descrittivi per facilitare il debug. Quando lanci un'eccezione, puoi fornire un |_+_| messaggio come argomento. È possibile accedere a questo messaggio nel blocco catch utilizzando |_+_| ma se l'eccezione non viene mai rilevata, il messaggio verrà visualizzato anche come parte dell'analisi dello stack.
  • Cerca di non catturare e ignorare le eccezioni. Per aggirare l'inconveniente delle eccezioni controllate, molti programmatori principianti e pigri imposteranno un blocco catch ma lo lasceranno vuoto. Cattivo! Maneggialo sempre con grazia, ma se non puoi, stampa almeno una traccia dello stack in modo da sapere che l'eccezione è stata generata. Puoi farlo usando il |_+_| metodo.
  • Attenzione all'uso eccessivo delle eccezioni. Quando hai un martello, tutto sembra un chiodo. Quando impari per la prima volta sulle eccezioni, potresti sentirti obbligato a trasformare tutto in un'eccezione... al punto in cui la maggior parte del flusso di controllo della tua applicazione si riduce alla gestione delle eccezioni. Ricorda, le eccezioni sono pensate per gli eventi 'eccezionali'!

Ora dovresti essere abbastanza a tuo agio con le eccezioni per capire cosa sono, perché vengono utilizzate e come incorporarle nel tuo codice. Se non comprendi appieno il concetto, va bene! Mi ci è voluto un po' prima che 'facesse clic' nella mia testa, quindi non sentirti come se avessi bisogno di affrettarti. Prenditi il ​​tuo tempo.

Hai qualche domanda? Conosci altri suggerimenti relativi alle eccezioni che mi sono perso? Condividili nei commenti qui sotto!

Condividere Condividere Tweet E-mail Come creare un diagramma di flusso di dati per visualizzare i dati di qualsiasi progetto

I diagrammi di flusso dei dati (DFD) di qualsiasi processo ti aiutano a capire come i dati fluiscono dall'origine alla destinazione. Ecco come crearlo!

Leggi Avanti
Argomenti correlati
  • Programmazione
  • Giava
Circa l'autore Joel Lee(1524 Articoli Pubblicati)

Joel Lee è l'editore capo di MakeUseOf dal 2018. Ha un B.S. in Informatica e oltre nove anni di esperienza professionale di scrittura e modifica.

come ottenere mac os su Windows 10
Altro da Joel Lee

Iscriviti alla nostra Newsletter

Iscriviti alla nostra newsletter per suggerimenti tecnici, recensioni, ebook gratuiti e offerte esclusive!

Clicca qui per iscriverti