Una excepción es un error que ocurre en tiempo de ejecución haciendo que el programa termine de forma inesperada. Veamos un ejemplo:

Si se introducen los datos adecuados al ejecutar la clase, el resultado será el esperado.

Ahora bien, que ocurre si no se introducen en el formato esperado? Se produce una excepción y la ejecución del programa se detiene sin llegarse a completar.
Para evitar que el programa termine al generarse una excepción, tenemos la opción de capturarla y de esta forma la ejecución continúa.
Realmente una excepción es un objeto de tipo Exception. Cuando la máquina virtual se encuentra con un error que no puede resolver genera una instancia de una clase que hereda de Exception. El tipo de clase elegido será el del tipo de problema encontrado. Si utilizamos un bloque try-catch para capturar excepciones, lo que realmente pretendemos es capturar ese objeto generado por la maquina virtual. De esta forma evitamos que se interrumpa la ejecución. Utilizamos el bloque try para encerrar aquellas instrucciones «peligrosas», nos referimos a las sentencias donde se podría generar una excepción. El bloque catch es donde capturamos la excepción. Veamos el ejemplo anterior mejorado.

La ejecución daría el siguiente resultado:

Qué está ocurriendo? Por qué no muestra el resultado de la suma? El problema es el siguiente: Cuando se lee el primer argumento («1») se realiza la conversión a tipo entero y se acumula a la suma. Cuando se lee el segundo argumento («two»), al intentar hacer la conversión a tipo entero se genera una excepción de tipo NumberFormatException, en este momento se ejecuta el bloque catch para capturar dicha excepción.
El resto de los argumentos ya no se evalúan y tampoco se imprime el resultado final de la suma. Para evitar esto, todavía podríamos mejorar más nuestro código haciendo que sólo la instrucción peligrosa forme parte del bloque try. De esta forma, se evaluarán todos los argumentos y se mostrará la suma. Veamos cómo hacerlo.

La ejecución dará ahora el siguiente resultado:

Podemos utilizar múltiples bloques catch pero debemos seguir la regla de declararlos del más especifico al más genérico. En caso contrario se genera un error de compilación. También podemos utilizar try-catch-finally. El bloque finally nos asegura que se ejecutará siempre haya excepción o no. Un buen ejemplo de uso del bloque finally es cuando abrimos una conexión a la base de datos y siempre se debería de cerrar se haya producido una excepción o no. Pues bien, el cierre de la conexión iría dentro del bloque finally.
MANEJO DE EXCEPCIONES MÚLTIPLES
Cuando nos encontramos que podemos tener diferentes excepciones en una ejecución poemos incluirlas todas en un solo bloque.
|
1 2 3 4 5 6 |
public void newMu ltiCatch( ){ try{ methodThatThrowsThreeExceptions( ); }catch(ExceptionOne | ExceptionTwo | ExceptionThree e){ } } |
Sin embargo, si tienes excepciones que pertenecen a distintos tipos que deben manejarse de distinta manera, se puede hacer lo siguiente:
|
1 2 3 4 5 6 7 8 9 |
public void newMultiMultiCatch( ){ try{ methodThatThrowsThreeExceptions( ); }catch (ExceptionOne e){ //maneja ExceptionOne }catch (ExceptionTwo | ExceptionThree e){ //maneja ExceptionTwo y ExceptionThree } } |
API EXCEPTION
El API Exception nos permite ver las diferentes clases de las excepciones y la forma en que están organizadas. Como vemos en el diagrama, la clase Exception hereda de la clase Throwable y hermana de ella tenemos la clase Error. Los errores no se pueden capturar. Cuando ocurren el programa termina sin que podamos hacer nada.

PROPAGAR EXCEPCIONES
Si no queremos capturar una excepción generada tenemos otra opción que es lanzarla. Para lanzar una excepción añadimos la clausula throws en el método donde se puede generar la excepción. En este caso, la excepción se propaga a la instrucción donde se ha efectuado la llamada al método. Veamos ejemplos:

REGLAS DE SOBREESCRITURA DE METODOS QUE LANZAN EXCEPCIONES
Si queremos sobrescribir o redefinir un método con clausula throws aquí tenemos las reglas a seguir:
- Se puede sobrescribir el método eliminado la cláusula throw
- No se puede sobrescribir para que lance más excepciones que las definidas
- Puede lanzar excepciones de una subclase de la definida originalmente.
- No puede lanzar excepciones que sean de la superclase de la definida en un principio.
EXCEPCIONES PERSONALIZADAS
A pesar de que el API Exception nos ofrecen muchas clases para manejar excepciones, muchas veces nos vamos a encontrar con la situación de querer crear nuestra propia excepción, a eso lo denominamos excepciones personalizadas o propias. Gracias al mecanismo de herencia, para generar nuestra propia excepción es suficiente con crear una clase que herede de la clase Exception. Veamos un ejemplo:


En este ejemplo estamos propagando la excepción con throws. También podríamos haberla capturado con un bloque try-catch o try-catch-finally.