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