Excepciones en Java
Introducción
En el mundo del desarrollo de software se conoce como “exception” a un evento excepcional que ocurre en un programa en ejecución y este altera el flujo normal de las instrucciones.
¿Que ocurre en Java?
Cuando ocurre un error dentro de un método de una de las clases de una aplicación Java el sistema de ejecución crea un objeto de tipo excepción que contiene información sobre el error ocurrido, una vez creado el objeto el sistema inicia una búsqueda para encontrar un bloque de código capaz de manejar la excepción generada (exception handler). Esta búsqueda se inicia desde el método donde se generó el error yendo por cada uno de los métodos que fueron invocados hasta llegar a él (call stack). Si el sistema de ejecución encuentra un bloque de código apropiado para el manejo de la excepción el objeto es transferido a este bloque (exception catch). De lo contrario, si el sistema de ejecución no encuentra ningún método capaz de manejar la excepción en todo el call stack el programa finalizará.
La regla de Capturar o declarar las excepciones
Todo programa escrito en Java debe seguir la regla conocida como “Captura o especifica las excepciones”. Esto significa que todo código que pueda generar ciertos tipos de excepciones debe cumplir con alguno de los dos siguientes estatutos:
- Capturar la excepción utilizando la instrucción try.
- Especificar que el método puede generar cierta(s) excepciones utilizando la instrucción throws.
El código del programa Java que no cumpla alguna de las dos condiciones anteriores no va compilar, esta regla no aplica para todos los tipos de excepciones de Java como se explica más adelante.
Las excepciones en Java pueden clasificarse en tres tipos o categorías: Checked Exceptions, Errors y Runtime Exceptions.
Checked Exceptions
En esta categoría caen las excepciones que pueden ser anticipadas cuando se está escribiendo un programa, por ejemplo si se escribe un programa para abrir un archivo y dicho programa recibe la ruta y el nombre del archivo como parámetros debe tenerse en cuenta que en caso de que el archivo no exista en la ruta especificada se va a generar una excepción (Ej. java.io.FileNotFoundException). Un programa bien escrito debe capturar esta excepción y tomar una decisión, por ejemplo notificar al usuario y preguntar por una ruta correcta del archivo.
Las checked exceptions deben cumplir la regla de “Captura o Especifica”, todas las excepciones en Java son checked exceptions, excepto aquellas que son instancias de las clases Error, RuntimeException o sus subclases.
Error
Una excepción de este tipo indica un error grave que la aplicación no debe intentar capturar, generalmente se trata de condiciones anormales y externas que afectan al programa y este no puede anticiparlas o recuperarse de las mismas. Por ejemplo retomando el ejemplo del programa que abre un archivo, suponiendo que la ruta sea correcta, el programa abre el archivo pero no puede iniciar la lectura debido a un problema en el disco duro. El sistema de ejecución lanzará una excepción de tipo java.io.IOError, el programa podría capturar esta excepción pero en estos casos lo lógico sería notificar el evento y terminar el programa.
Las excepciones de este tipo no están obligadas a cumplir la regla de “Captura o Especifica”. Estas excepciones están representadas por la clase java.lang.Error y sus subclases.
Runtime Exceptions
El tercer tipo o categoría de las excepciones en Java son las excepciones que ocurren en tiempo de ejecución (Runtime Exceptions). Estas representan condiciones excepcionales internas a la aplicación pero que generalmente la aplicación no puede anticiparlas o recuperarse de ellas. Podemos citar como ejemplos los bugs, errores en la lógica del programa, uso inapropiado de una librería. Por ejemplo un programa que intenta invocar un método de un objeto y debido a un error en la lógica cuando se alcanza esa línea el objeto tiene el valor null, el sistema de ejecución lanzará una excepción de tipo NullPointerException, la aplicación podría capturar esta excepción pero tendría mejor sentido modificar el código fuente para reparar la lógica que causa la excepción.
Las excepciones de este tipo tampoco están obligadas a cumplir la regla de “Captura o Especifica”. Estas excepciones están representadas por la clase java.lang.RuntimeException y sus subclases.
Las excepciones de tipo Error y RunTimeException se conocen como unchecked exceptions.
Notas Importantes sobre excepciones
- Para lanzar excepciones utilizando la instrucción throw la instancia debe ser de una clase descendiente de Throwable.
- La mayoría de las excepciones que normalmente se capturan o lanzan en los programas son descendientes de la clase Exception.
- Cuando ocurre algún error de hardware, “linkeo”, etc. La Máquina Virtual de Java lanza una excepción de tipo Error.
- La clase RuntimeException está reservada para representar excepciones relacionadas con el uso indebido de las APIs. Por ejemplo invocar el método de un objeto que almacena una referencia nula.
- Si el cliente de la clase que escribimos tendrá la posibilidad de recuperarse de una excepción entonces debemos crearla como checked lo cual se traduce a una subclase de la clase Exception, pero si el cliente no podrá hacer nada para recuperarse de la excepción entonces debemos crearla como unchecked lo cual se traduce como subclase de RuntimeException (por ejemplo si se escribe un método que genera una excepción si uno de los parámetros de entrada es nulo).
Diagrama de la clase Throwable
