Una excepción es un evento que al ocurrir durante la ejecución de un programa, impide su continuación normal. Por ejemplo: intentar dividir un número por cero, intentar acceder fuera de los límites de una matriz, un fallo hardware, etc.Cuando ocurre uno de estos errores en un método Java, el método crea un objeto de excepción y se lo pasa al sistema de control de ejecución (runtime system). Esta operación se conoce por "lanzar una excepción" (throw an exception). El sistema de control de ejecución es responsable de buscar un segmento de código ( exception handler) que resuelva la excepción.
El sistema de control de ejecución busca en la pila de llamadas, hasta que encuentra un método con un manejador que acepta excepciones del mismo tipo que la generada. Si no encuentra ningún manejador apropiado, termina el programa.
El tratamiento de excepciones tiene las siguientes ventajas:
- Separar el tratamiento de errores del código "normal"
Veamos un ejemplo de una función que lee un fichero en memoria:Sin un tratamiento diferenciado de excepciones, la función quedaría:leeFichero { abre el fichero; determina su tamaño; reserva espacio en memoria; lee el fichero en memoria; cierra el fichero; }Utilizando el mecanismo de excepciones de Java, obtendríamos el siguiente código mucho más claro y conciso:tipoCódigoError leeFichero{ inicializa códigoError = 0; abre el fichero; if (ficheroAbierto) { determina el tamaño del fichero; if (obtenidoTamañoFichero) { reservar espacio en memoria; if (obtenidaSuficienteMemoria) { lee el fichero en memoria; if (falloLectura) { códigoError = -1; } } else { códigoError = -2; } } else { códigoError = -3; } cierra fichero; if (ficheroNoCerrado && códigoError == 0) { códigoError = -4; } else { códigoError = códigoError and -4; } } else { códigoError = -5; } return códigoError; }leeFichero { try{ abre el fichero; determina su tamaño; reserva espacio en memoria; lee el fichero en memoria; cierra el fichero; } catch (falloAbriendoFichero) { hazAlgo; } catch (falloDeterminandoTamañoFichero) { hazAlgo; } catch (falloReservandoMemoria) { hazAlgo; } catch (falloLectura) { hazAlgo; } catch (falloCerrandoFichero) { hazAlgo; } }- Propagación de errores en la pila de llamadas
De esta formamétodo1 { try { call método2; } catch (exception) { procesaError; } } método2 throws exception { call método3; } método3 throws exception { call leeFichero; }método2
ymétodo3
no tienen que preocuparse de propagar errores ocurridos enleeFichero
, puesto que esto se lleva a cabo de una forma natural en Java.
- Agrupamiento de tipos de errores y diferenciación de errores
Puesto que las excepciones son objetos de Java, es sencillo agruparlas en clases y subclases. De esta forma, un manejador muy específico puede recoger excepciones de una subclase dada, mientras que otro más general puede recoger clases de excepciones más generales.
En Java hay muchos tipos de excepciones:En tiempo de compilación se comprueba que las checked exceptions (todas las exceciones que no sean de tiempo de ejecución) se capturen o declaren en los métodos donde pueden darse.
- de tiempo de ejecución (runtime)
- aritméticas (división por cero, etc.)
- de punteros (acceso a un objeto a través de una referencia nula, etc.)
- de índices (acceder a una posición demasiado grande de una matriz, etc.)
- de entrada/salida
- definidas por el usuario, etc.
La captura se hace mediante la sentencia
catch
que proporciona el código para tratar la excepción.catch (IOException e) { procesarError; }La declaración se hace por medio de la sentencia
throws
en la declaración del método.
Los pasos a seguir cuando queremos escribir un código en el que puedan surgir excepciones son los siguientes:métodoLanzaExcepción (...) throws IOException { ... }
- Rodear la sentencia (o bloques de sentencias) sujeta(s) a levantar excepciones con una sentencia
try
.- Si queremos tratar una excepción, capturarla con una sentencia
catch
y dar un código adecuado para solucionar la situación de error.- Si queremos que se ejecute un código final, independientemente de si han surgido excepciones o no, utilizar una sentencia
finally
.