Contenidos
Excepciones en Java
Si una operación no puede completarse debido a un error, el programa deberá:
-
volver a un estado estable y permitir otras operaciones
-
intentar guardar el trabajo y finalizar
Esta tarea es difícil debido a que generalmente el código que detecta el error no es el que puede realizar dichas tareas por eso debe informar al que pueda manejarlo
La solución más habitual son los códigos de error
Java ofrece otra forma de tratar con los errores en condiciones excepcionales: las excepciones
Una condición excepcional es aquella que impide la continuación de una operación
No se sabe como manejarla, pero no se puede continuar
En Java se lanza una excepción para que alguien que sepa manejarla la trate en un contexto superior
En el ejemplo se comprueba de forma condicional si el fichero readme.txt existía en el sistema y en caso de no existir se lanza la excepción IOException que de momento está sin tratar
La palabra reservada throw finaliza el método actual y lanza un objeto que facilite información sobre el error ocurrido
Normalmente se utilizará una clase para cada tipo de error
Java obliga a que un método informe de las excepciones explícitas que pueda lanzar
Un método no solo tiene que decir que devuelve si todo va bien; debe indicar también qué puede fallar
En el ejemplo se han declarado las excepciones EOFException y FileNotFoundException que afectaban al método fichero
La especificación de excepciones se realiza mediante la palabra throws en la declaración del método y puede haber tantas como necesitemos separadas por un espacio
Manejo de la excepciones
Una vez detectado el error hace falta indicar quien se encarga de tratarlo
Un manejador de excepciones tiene el siguiente formato:
El bloque try delimita el grupo de operaciones que puede producir excepciones
El bloque catch es el lugar al que se transfiere el control si alguna de las operaciones produce una excepción
En el ejemplo se ha usado un bloque try con su bloque catch para gestionar los errores del ejemplo anterior
Si alguna de las operaciones del bloque produce una excepción, se interrumpe el bloque try y se ejecuta el catch
Al finalizar este, se continua normalmente
Si no se produce ninguna excepción, el bloque catch se ignora
También existe la posibilidad de utilizar la excepción genérica Exception, pero es más recomendable usar el tipo de excepción específica para el error
En el ejemplo se ha usado un bloque try con su bloque catch para gestionar varias excepciones como en el ejemplo anterior
Un bloque try puede tener varios catch asociados
Cuando una excepción no se corresponde con ningún catch se propaga hacia atrás en la secuencia de invocaciones hasta encontrar un catch adecuado
En el ejemplo se gestionan las excepciones de los métodos f1 y f2 y si no encuentran ninguna continua la ejecución del código de forma normal fuera del bloque try
En este ejemplo se han tratado de mostrar las 3 alternativas que podemos usar para tratar la excepción IOException desde el método f2
Cuando se invoca un método que lanza excepciones es obligatorio:
-
que se maneje el error con un bloque catch
-
que se indique mediante throws su propagación
Bloque finally
Puede haber ocasiones en que se desea realizar alguna operación tanto si se producen excepciones como si no
Dichas operaciones se pueden situar dentro de un bloque finally
Un bloque finally tiene el siguiente formato:
Si no hay ninguna excepción se ejecutará el bloque try y el finally
En el ejemplo se ha controlado el cierre del archivo f en el bloque finaly, ejecutándose siempre
Si se produce alguna excepción:
-
Si es atrapada por un catch del mismo try se ejecuta este y luego el finally
La ejecución continua después del finally normalmente
-
Si no es atrapada se ejecuta el finally y la excepción se propaga al contexto anterior
Jerarquía de las excepciones
Toda excepción debe ser una instancia de la clase de Throwable
De ella hereda los siguientes métodos:
- getMessage()
devuelve una cadena con un mensaje que detalla de detalla excepción
- toString()
devuelve una descripción breve que es el resultado es concatenar:
- el nombre de la clase de este objeto
- el token :
- el resultado del método getLocalizedMessage() de este objeto
- fillInStackTrace()
registra información sobre el estado actual de los marcos de pila para el subproceso actual
Si el estado de la pila no se puede escribir, no habrá valor devuelto
- printStackTrace()
devuelve la traza que ha seguido la excepción
La primera línea de salida contiene el resultado del método toString() de este objeto
Las líneas restantes representan los datos registrados previamente por el método fillInStackTrace()
La base de la jerarquía de excepciones de Java es:
-
Throwable
-
Error
-
Exception
-
RuntimeException
-
-
Las clases derivadas de Error describen errores internos de la JVM:
-
no deben ser lanzados por las clases de usuario
-
estas excepciones rara vez ocurren y cuando así sea lo único que se puede hacer es intentar cerrar el programa sin perder los datos
-
Ejemplos: OutOfMemoryError; StackOverflow; etc
Los programas en Java trabajarán con las excepciones de la rama Exception
Este grupo se divide a su vez en:
-
Las clases que derivan directamente de Exception (explícitas)
-
Las que derivan de RuntimeException (implícitas)
Se utilizan las RunTimeException para indicar un error de programación
Si se produce una excepción de este tipo hay que arreglar el código
Ejemplos:
-
Un cast incorrecto
-
Acceso a un array fuera de rango
-
Uso de un puntero null
El resto de Exception indican que ha ocurrido algún error debido a alguna causa ajena al programa
Ejemplos:
-
Un error de E/S
-
Error de conexión
Declaración de excepciones
Los métodos deben declarar sólo las excepciones explícitas
Las implícitas no deben declararse (aunque pueden producirse igualmente)
Por tanto cuando un método declara una excepción avisa de que puede producirse dicho error además de cualquier error implícito
Creación de excepciones
Si se necesita gestionar algún error no contemplado por los estándar que dispone Java, podemos crear nuestra propia clase de excepción
La única condición es que la clase derive de Throwable o de alguna que derive de ella
En la práctica generalmente se derivarán:
-
de RunTimeException si se desea notificar un error de programación
-
de Exception en cualquier otro caso
Excepciones explícitas | Excepciones implícitas |
---|---|
Derivan de Exception (no de RunTimeException) | Derivan de RunTimeException |
Indican un error externo a la aplicación | Indican un error de programación |
Si se lanzan es obligatorio declararlas | No se declarar: se corrigen |
Si se invoca un método que las lanza es obligatorio atraparlas o declararlas |
Se pueden atrapar En caso contrario, finaliza la aplicación |
Excepciones y herencia
Al redefinir un método se está dando otra implementación para un mismo comportamiento
El nuevo método sólo podrá lanzar las excepciones declaradas en el método original
En el ejemplo se ha redefinido el método f de la clase A en la clase B con una excepción adicional
Un método puede declarar excepciones que no lance realmente
Así un método base puede permitir que las redefiniciones puedan producir excepciones
Los constructores, al no heredarse, pueden lanzar nuevas excepciones
Normas de uso
-
Norma
-
Si una excepción se puede manejar no debe propagarse
-
Es más cómodo usar métodos que no produzcan errores
-
-
Norma
-
No utilizar las excepciones para evitar una consulta
-
No abusar de ellas
-
-
-
Norma
-
Separar el tratamiento de errores de la lógica
Todo junto Separado
-
-
Norma
-
No ignorar una excepción ya que dejamos el código con errores sin controlar
-