Bloki try {} catch(..) {} catch(..) {} finally {}
Ogólny schemat stosowania bloków try {} catch(..) {} catch(..) {} finally {}:
try {
...
...
} catch( <EXCEPTION_CLASS_A> e ) {
... // reakcja
} catch( <EXCEPTION_CLASS_B> e ) {
... // reakcja
} catch( <EXCEPTION_CLASS_C> e ) {
... // reakcja
} finally {
... //kod, który ma się wykonać zarówno gdy wystąpi wyjątek jak i wówczas gdy nie wystąpi
}
Przyjmijmy, że dopóki użytkownik nie wprowadzi poprawnej wartości to będzie o nią proszony do skutku. Tym razem do pobrania danych od użytkownika użyjemy obiektu BufferedReader i dostępnej w nim metody readLine() pobierającej od użytkownika String, a następnie dokonamy rzutowania na wartość int przy pomocy statycznej metody parseInt() klasy osłonowej Integer - w tym ostatnim kroku, jeśli zostanie wygenerowany wyjątek typu NumberFormatException poprosimy użytkownika o ponowne podanie wartości.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ExceptionTestProgram1 {
public static void main( String[] args ){
int tablica[] = { 11, 22, 33 };
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader( System.in ) ); // opakowujemy mało wydajny InputStreamReader w wydajny BufferedReader
System.out.print( "Podaj numer elementu w tablicy: " );
int index = -1;
boolean properValueEntered = false;
while( !properValueEntered ) {
try {
index = Integer.parseInt( bufferedReader.readLine() );
} catch( NumberFormatException n ) {
System.out.print( "Niepoprawne dane! Podaj numer: " );
} catch(IOException e) {
System.out.println( "IOException - Błąd odczytu danych" );
}
properValueEntered = index == -1 ? false : true;
}
try {
System.out.println( tablica[index-1] );
} catch( ArrayIndexOutOfBoundsException e ) {
System.out.println( "Niepoprawna wartość. Rozmiar tablicy to: " + tablica.length );
}
}
}
Można jeszcze uprościć kod, rezygnując ze zmiennej wprowadzonaPoprawnaWartosc i zamiast niej wstawić instrukcję break;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ExceptionTestProgram4 {
public static void main( String[] args ){
int tablica[] = { 11, 22, 33 };
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(System.in) );
System.out.print( "Podaj numer elementu w tablicy: " );
int index = -1;
while( true ) {
try {
index = Integer.parseInt( bufferedReader.readLine() );
break; //tutaj sterowanie dochodzi wyłącznie wówczas, gdy nie wystąpi wyjątek
} catch ( NumberFormatException n ) {
System.out.print( "Niepoprawne dane! Podaj numer: " );
} catch ( IOException e ) {
System.out.println( "IOException - Błąd odczytu danych" );
}
}
try {
System.out.println( "Element tablicy na pozycji " + index + " to: " + tablica[index-1] );
} catch ( ArrayIndexOutOfBoundsException e ) {
System.out.println( "Niepoprawna wartość. Rozmiar tablicy to: " + tablica.length );
}
}
}
...i jeszcze jedna wersja - tym razem wstawiamy kod wyświetlający wartość z tabeli do pierwszego bloku try:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class ExceptionTestProgram5 {
public static void main( String[] args ){
int tablica[] = { 11, 22, 33 };
BufferedReader bufferedReader = new BufferedReader( new InputStreamReader(System.in) );
System.out.print( "Podaj numer elementu w tablicy: " );
int index = -1;
while( true ) {
try {
index = Integer.parseInt( bufferedReader.readLine() );
System.out.println( "Element tablicy na pozycji " + index + " to: " + tablica[index-1] );
break; //tutaj sterowanie dochodzi wyłącznie wówczas, gdy nie wystąpi wyjątek
} catch ( NumberFormatException e ) {
System.out.print( "Niepoprawne dane! Podaj numer: " );
} catch ( ArrayIndexOutOfBoundsException e ) {
System.out.print( "Niepoprawna wartość. Rozmiar tablicy to: " + tablica.length + " Podaj numer: " );
} catch ( IOException e ) {
System.out.println( "IOException - Błąd odczytu danych" );
}
}
}
}
Dlaczego należy używać bloku finally:
https://stackoverflow.com/questions/3861522/do-you-really-need-the-finally-block
Sytuacja, w której kod zapisany po bloku finally nie jest wykonywany (gdy w bloku try oraz catch zwracamy wartość przy użyciu instrukcji return). Jeśli w bloku catch nie używamy instrukcji return, wówczas kod występujący po bloku finally zostanie wykonany.
public class FinallyBlockTest {
static String testFunction() {
try {
int x = 0;
int y = 1 / x;
return "Result: " + y;
}
catch (Exception e){
System.err.println("Exception: " + e.getMessage());
return "NULL";
}
finally {
System.out.println("finally executed");
}
// Unreachable Code
// System.out.println("finally!");
}
public static void main(String[] args) {
System.out.println("Function returned: " + testFunction());
}
}
//WYNIK:
//Exception: / by zero
//finally executed
//Function returned: NULL