English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
In questo tutorial, imparerai come gestire le eccezioni in Java utilizzando esempi. Per gestire le eccezioni, utilizzeremo il blocco try ... catch ... finally.
Nell'ultimo tutorial, abbiamo imparato le eccezioni. Un'eccezione è un evento inaspettato che si verifica durante l'esecuzione del programma.
In Java, utilizziamo i componenti di gestione delle eccezioni try, catch e finally per gestire le eccezioni.
Per catturare ed elaborare le eccezioni, mettiamo il blocco di codice try...catch...finally intorno al codice che potrebbe generare un'eccezione. Il blocco finally è opzionale.
La sintassi di try...catch...finally è la seguente:
try { // codice } catch (ExceptionType e) { // blocco di cattura } // blocco finally }
Il codice che potrebbe generare un'eccezione dovrebbe essere messo all'interno di un blocco try.
Dopo ogni blocco try dovrebbe seguire un blocco catch o finally. Quando si verifica un'eccezione, viene catturata dal blocco che segue immediatamente.
Il blocco catch non può essere utilizzato separatamente; deve seguire immediatamente il blocco try.
class Main { public static void main(String[] args) { try { int divideByZero = 5 / 0; System.out.println("Il resto del codice nel blocco try"); } catch (ArithmeticException e) { System.out.println("ArithmeticException => " + e.getMessage()); } } }
输出结果
ArithmeticException => / by zero
In questo esempio
Nel blocco try, dividiamo un numero per zero. Questo genera un'ArithmeticException.
Quando si verifica un'eccezione, il programma salta il resto del codice nel blocco try.
In questo esempio, abbiamo creato un blocco catch per gestire l'ArithmeticException. Pertanto, vengono eseguite le istruzioni nel blocco catch.
Se tutte le istruzioni nel blocco try non generano eccezioni, il codice del blocco catch viene saltato.
Per ogni blocco try, possono esserci zero o più blocchi catch.
Il tipo di parametro di ogni blocco catch indica il tipo di eccezione che può essere gestita. I blocchi catch multipli ci permettono di gestire ogni eccezione in modo diverso.
class ListOfNumbers { public int[] arrayOfNumbers = new int[10]; public void writeList() { try { arrayOfNumbers[10] = 11; } System.out.println("NumberFormatException => " + e1.getMessage()); } System.out.println("IndexOutOfBoundsException => " + e2.getMessage()); } } } class Main { public static void main(String[] args) { ListOfNumbers list = new ListOfNumbers(); list.writeList(); } }
输出结果
IndexOutOfBoundsException => Indice 10 fuori dai limiti per lunghezza 10
In questo esempio, abbiamo dichiarato un array di interi arrayOfNumbers di dimensione 10.
Sappiamo che l'indice dell'array parte sempre da 0. Pertanto, quando proviamo ad assegnare un valore all'indice 10, si verifica un'IndexOutOfBoundsException, poiché il limite dell'array arrayOfNumbers è 0 a 9.
Quando si verifica un'eccezione nel blocco try
L'eccezione viene lanciata al primo blocco catch. Il primo blocco catch non gestisce l'eccezione IndexOutOfBoundsException, quindi viene passata al blocco catch successivo.
Nel secondo blocco catch dell'esempio sopra, il gestore delle eccezioni è appropriato perché gestisce l'IndexOutOfBoundsException. Pertanto, viene eseguito.
Per ogni blocco try, può esserci solo un blocco finally.
finally块是可选的。但是,如果已定义,它将始终执行(即使不会发生异常)。
如果发生异常,则在try...catch块之后执行。如果没有异常发生,则在try块之后执行。
finally块的基本语法为:
try { //code } catch (ExceptionType1 e1) { // catch 块 } catch (ExceptionType1 e2) { // catch 块 } //finally块一直执行 }
class Main { public static void main(String[] args) { try { int divideByZero = 5 / 0; } catch (ArithmeticException e) { System.out.println("ArithmeticException => " + e.getMessage()); } System.out.println("Finally块总是执行"); } } }
输出结果
ArithmeticException => / by zero Finally块总是执行
在此示例中,我们将数字除以0。这引发了一个ArithmeticException被catch块捕获,finally块始终执行。
使用finally块被认为是一种很好的做法。这是因为它包含了重要的清理代码,例如
可能被return、continue或break语句意外跳过的代码
关闭文件或连接
我们已经提到,finally总是执行,通常是这样的。但是,在某些情况下,finally块不执行:
使用 System.exit()方法
finally块中发生异常
线程被终止
让我们举一个实例,我们尝试使用FileWriter创建一个新文件,并使用PrintWriter写入数据。
import java.io.*; class ListOfNumbers { private int[] list = new int[10]; public ListOfNumbers() { //在列表数组中存储整数值 for (int i = 0; i < 10; i++) { list[i] = i; } } } public void writeList() { PrintWriter out = null; try { System.out.println("entrare nella语句try"); //Crea un nuovo file OutputFile.txt out = new PrintWriter(new FileWriter("OutputFile.txt")); //Scrivi i valori dall'array della lista in un nuovo file creato for (int i = 0; i < 10; i++) { out.println("Value at: " + i + " = " + list[i]); } } System.out.println("IndexOutOfBoundsException => " + e1.getMessage()); } System.out.println("IOException => " + e2.getMessage()); } //Verifica se PrintWriter è stato aperto if (out != null) { System.out.println("Chiudi PrintWriter"); out.close(); } else { System.out.println("PrintWriter non può essere aperto"); } } } } class Main { public static void main(String[] args) { ListOfNumbers list = new ListOfNumbers(); list.writeList(); } }
Quando esegui questo programma, possono verificarsi due possibilità:
Si verifica un'eccezione nel blocco try
Il blocco try viene eseguito correttamente
Potrebbe verificarsi un'eccezione durante la creazione di un nuovo FileWriter. Se non è possibile creare o scrivere il file specificato, viene lanciata IOException.
Quando si verifica un'eccezione, otteniamo il seguente output.
Entra nella struttura try IOException => OutputFile.txt PrintWriter non può essere aperto
Quando non si verifica un'eccezione e il blocco try viene eseguito correttamente, otteniamo il seguente output.
Entra nella struttura try Chiudi PrintWriter
Creeremo un file OutputFile.txt e conterrà il seguente contenuto
Value at: 0 = 0 Value at: 1 = 1 Value at: 2 = 2 Value at: 3 = 3 Value at: 4 = 4 Value at: 5 = 5 Value at: 6 = 6 Value at: 7 = 7 Value at: 8 = 8 Value at: 9 = 9
Con l'aiuto degli esempi sopra menzionati, cerchiamo di comprendere meglio il flusso di gestione delle eccezioni.
L'immagine sopra descrive il flusso di esecuzione del programma quando si verifica un'eccezione durante la creazione di un nuovo FileWriter.
Per trovare il metodo che ha sollevato l'eccezione, il metodo main chiama il metodo writeList(), che a sua volta chiama il metodo FileWriter() per creare un nuovo file OutputFile.txt.
Quando si verifica un'eccezione, il sistema di esecuzione salta il resto del codice nel blocco try.
Inizia a cercare in senso inverso la pila delle chiamate per trovare il gestore di eccezioni appropriato.
In questo caso, il FileWriter non ha gestori di eccezioni, quindi il sistema di esecuzione controlla il metodo successivo nella pila delle chiamate, ovvero writeList.
Il metodo writeList ha due gestori di eccezioni: uno per l'IndexOutOfBoundsException e l'altro per l'IOException.
Poi, il sistema gestisce questi gestori in successione.
Nel presente esempio, il primo gestore gestisce l'IndexOutOfBoundsException. Questo non corrisponde all'IOException sollevata nel blocco try.
Quindi, si verifica quale sia il programma di gestione delle IOException successivo. Se corrisponde al tipo di eccezione sollevata, esegue il codice del blocco catch corrispondente.
Dopo aver eseguito il programma di gestione delle eccezioni, viene eseguito il blocco finally.
In questa scena, poiché si è verificata un'eccezione nel FileWriter, l'oggetto PrintWriter out non è mai stato aperto e non è necessario chiuderlo.
Ora, supponiamo che durante l'esecuzione del programma non si sia verificata alcuna eccezione e il blocco try viene eseguito correttamente. In questo caso, verrà creato e scritto un file OutputFile.txt.
Notoriamente, l'esecuzione del blocco finally è indipendente dal trattamento delle eccezioni. Poiché non si è verificata alcuna eccezione, PrintWriter è stato aperto e deve essere chiuso. Questo viene fatto tramite la frase out.close() nel blocco finally.
Dalla versione Java SE 7 in poi, possiamo ora catturare più di un tipo di eccezione con un singolo blocco catch.
Questo riduce la ripetizione del codice e migliora la semplicità ed efficienza del codice.
Ciascun tipo di eccezione che può essere gestita dal blocco catch deve essere separato da un trattino verticale (|).
La sua sintassi è:
try { // code catch (ExceptionType1 | Exceptiontype2 ex) { // catch block }
Per ulteriori informazioni, visitareJava cattura più eccezioni.
L'espressione try-with-resources è un tipo di statement try che ha una o più dichiarazioni di risorse.
La sua sintassi è:
try (resource declaration) { // use of the resource } catch (ExceptionType e1) { // catch block }
Le risorse sono oggetti che devono essere chiusi alla fine del programma. Devono essere dichiarati e inizializzati all'interno dello statement try.
Facciamo un esempio.
try (PrintWriter out = new PrintWriter(new FileWriter("OutputFile.txt"))) { // use of the resource }
L'espressione try-with-resources è anche chiamataGestione automatica delle risorse.Questa espressione chiude automaticamente tutte le risorse alla fine dello statement.
Per ulteriori informazioni, visitareEspressione try-with-resources Java.