Diseño de excepciones

La palabra reservada try designa un bloque try, que es un área de su programa que detecta excepciones. En el interior de bloques try, normalmente se llaman a métodos que pueden levantar o lanzar excepciones. La palabra reservada catch designa un manejador de capturas con una signatura que representa un tipo de excepción. Los manejadores de captura siguen inmediatamente a bloques try o a otro manejador catch con un argumento diferente.  

Los bloques try son importantes ya que sus manejadores de captura asociados determinan cuál es la parte de su programa que maneja una excepción específica. El código que está dentro del manejador de capturas (catch) es donde se decide lo que se hace con la excepción lanzada.

Java proporciona un manejador especial, denominado finally. Es opcional, de utilizarse debe escribirse después del último catch(). En general, la finalidad que tiene es liberar recursos asignados en el bloque try, por ejemplo cerrar archivos abiertos en alguna sentencia del bloque try. Este manejador tiene la propiedad de que siempre se ejecuta, una vez que ha terminado el bloque, o bien una vez que una excepción ha sido capturada por el correspondiente catch().

Bloques try

Un bloque try encierra las sentencias que pueden lanzar excepciones. El bloque comienza con la palabra reservada try seguida por una secuencia de sentencias de programa encerradas entre llaves. A continuación del bloque try hay una lista de manejadores, llamados cláusulas catch. Al menos un manejador catch debe aparecer inmediatamente después de un bloque try, o si no hay manejador catch debe especificarse el manejador finally. Cuando un tipo de excepción lanzada coincide con el argumento de un catch, el control se reanuda dentro del bloque del manejador catch. Si ninguna excepción se lanza desde un bloque try, una vez que terminan las sentencias del bloque, prosigue la ejecución a continuación del último catch. Si hay manejador finally (es opcional), la ejecución sigue por sus sentencias; una vez terminadas, continúa la ejecución en la sentencia siguiente.

Sintaxis

       try{
                  // código del bloque try
       }
       catch(signatura){
                  // código del bloque catch
       }

También se puede anidar bloques try.

       void sub(int n) throws Exception
       {
              try{
                          . . .      // bloque try externo
                          try{   // bloque try interno
                                     . . .
                                     if(n==1)
                                             return ;
                          }
                          catch(signatura1) {. . .}       //manejador catch interno
              }
              catch(signatura2) {. . .}                   // manejador catch externo
              . . .
       }

Una excepción lanzada en el bloque interior try ejecuta el manejador catch con signatura1 si coincide el tipo de excepción. El manejador catch con signatura2 maneja excepciones lanzadas desde el bloque try exterior si el tipo de la excepción coincide. El manejador externo de catch también captura excepciones lanzadas desde el bloque interior si el tipo de excepción coincide con signatura2 pero no con signatura1. Si los tipos de excepción no coinciden con ninguna signatura, la excepción se propaga al llamador de sub().

Normas

       try{
                  sentencias
       }
       catch(parámetro){
                  sentencias
       }
       catch(parámetro){
                  sentencias
       }
       etc.

  1. Cuando una excepción se produce en sentencias del bloque try hay un salto al primer manejador (catch) cuyo parámetro coincida con el tipo de excepción.
  2. Cuando las sentencias en el manejador se han ejecutado, se termina el bloque try y la ejecución prosigue en la sentencia siguiente. Nunca se produce un salto hacia atrás, al lugar en que ocurrió la interrupción.
  3. Si no hay manejadores para tratar con una excepción, se aborta el bloque try y la excepción se relanza.
  4. Si se utiliza el manejador opcional finally, se escribe después del último catch. La ejecución del bloque try, se lance o no una excepción, siempre termina con las sentencias de finally.

Precaución

Se puede transferir el control fuera de bloques try con una sentencia goto, return, break o continue. Si se ha especificado el manejador finally, primero se ejecuta este y después transfiere el control.

Ejemplo

El método calcularMedia() calcula una media de arreglos de tipo double; para ello invoca al método avg(). En el caso de ser llamado incorrectamente, avg() lanza excepciones del tipo MediaException.

La excepción que se va a lanzar en caso de error, MediaException, debe ser declarada como una clase derivada de Exception:

       class MediaException extends Exception{
                   //
       }

 El método calcularMedia() define un bloque try para tratar excepciones:

       double calcularMedia(int numero){
                    double b[] = {1.2 ,2.2, 3.3, 4.4, 5.5, 6.6};
                    double media;
                    try{
                                     media = avg(b,numero);            // cálculo media
                                     return media;
                    }
                    catch(MediaException mensaje){
                                     System.out.println(«Excepcion captada: » + mensaje);
                                     System.out.println(«Calcula media: uso de longitud del array «
                                                                               + b.length);
                                     numero = b.length;
                                     return avg(b,numero);
                    }
       }

El método avg() tiene que tener en la cabecera la excepción que puede lanzar:

       double avg(double []p, int n) throws MediaException

El método calcularMedia() define un arreglo de tipo double y llama a avg() con el nombre del arreglo (b) y un argumento de longitud (numero). Un bloque try contiene a avg() para capturar excepciones de tipo MediaException. Si avg lanza la excepción MediaException, el manejador de catch la capta, escribe un mensaje y vuelve a llamar a avg() con un valor predeterminado (la longitud del arreglo b).