domingo, 16 de mayo de 2021

El requerimiento de Atrapar o Especificar

Para que el codigo de un programa Java sea valido, debe hacer honor al requerimiento Atrapar o Especificar, en ingles Catch or Specify Requirement. Esto significa que el código que puede lanzar ciertas excepciones debería estar encerrado por uno de los siguientes:

Una sentencia try que atrape la excepción. La sentencia try debería proporcionar un manejador para la excepción, tal como se describe en Atrapando y Manejando Excepciones.

El metodo debería especificar las excepciones que puede lanzar. El metodo debería proporcionar una clausula throws con la lista de excepciones que pudiera lanzar, tal como se describe en Especificando las Excepciones que puede lanzar un metodo.

El codigo que no cumple con el principio de Catch or Specify Requirement ni siquiera compilara.

No todas las excepciones está sujetas a la regla Catch or Specify Requirement, como veremos más adelante. Para entender porqué, necesitamos revisar las tres categorias basicas de Excepciones, del cual solo una está sujeta a la regla mencionada.

Los tres tipos de Excepciones

El primer tipo de Excepción es la excepción verificada (Checked Exception). Estás son condiciones excepcionales que una aplicación bien diseñada debería anticiparse a ellas y recuperarse. Por ejemplo, suponga una aplicación que le solicita al usuario que ingrese el nombre de un archivo, para luego abrir el archivo pasandole el nombre ingresado al constructor de la clase java.io.FileReader. Normalmente, el usuario proporciona el nombre de un archivo que existe y es legible, entonces el constructor de la clase crea al objeto sin ningun problema y la ejecución de la aplicación continua con normalidad. Pero en ocasiones el usuario proporciona el nombre de un archivo que no existe, y el constructor lanza una excepción del tipo java.io.FileNotFoundException. Una aplicación bien escrita atrapará esta excepción y notificará el error al usuario, posiblemente solicitando el ingreso de un nombre de archivo correcto.

Las Excepciones Verificables (Checked Exceptions) están sujetas al principio Catch or Specify Requirement. Todas las excepciones son checked exceptions, excepto aquellas indicadas por Error, RuntimeException, y sus subclases.

El segundo tipo de excepciones es el tipo Error. Estas son aquellas condiciones excepcionales que son externas a la aplicación, y usualmente en donde la aplicación no puede anticiparse o recuperarse. Por ejemplo, supon que tenemos una aplicación que abre sin problemas un archivo para su lectura, pero no es posible leerlo porque hay un error de hardware o un error critico con el sistema de archivos. Este problema encontrado en la lectura lanzara un java.io.IOError. La aplicación puede atrapar esta excepción, con el fin de notificar al usuario del problema - pero tambien podría hacer sentido para el programa imprimir el stack trace (la secuencia de la llamada de los metodos) y salir.

Los errores no están sujetos al requisito de Atrapar o Especificar. Errores son aquellas excepciones indicadas por Error y sus subclases.

El tercer tipo de Excepciones son las excepciones en tiempo de ejecución (runtime exception en ingles). Estás son condiciones excepcionales que son internas a la aplicacion, y en las que usualmente la aplicacion no se puede anticipar o recuperar. Estas excepciones usualmente indican errores de programacion, errores logicos o por no usar correctamente una API. Por ejemplo, considera la aplicacion descrita anteriormente que pasa un nombre de archivo al constructor de la clase FileReader. Si un error de logica permite que una referencia null sea pasada al constructor, el constructor lanzará una excepción NullPointerException. La aplicación puede atrapar esta excepción, pero probablemente tenga mas sentido reparar la incidencia que causa que la excepción ocurra.

Las excepciones Runtime Exception no están sujetas al requerimiento Catch or Specify. Las excepciones Runtime Exception son aquellas indicadas por RuntimeException y sus subclases.

Errores y excepciones en tiempo de ejecución son categorizadas como excepciones no verificadas (unchecked exceptions).

Algunos programadores consideran el requerimiento Catch or Specify un defecto grave del mecanismo de las excepciones y lo dejan pasar usando excepciones no vericadas (unchecked exceptions) en lugar de excepciones verificadas (checked exceptions). En general, esto no es recomendado.

Ignorando el requerimiento Catch or Specify

La sección Excepciones no verificadas La controversia hablaremos acerca de cuando es apropiado el uso de excepciones no verificadas.

domingo, 9 de mayo de 2021

¿Qué es una Excepción en Java?

 Qué es una excepción?

El termino excepción hace a referencia a la frase "evento excepcional" o "evento inesperado." Una excepción es un evento excepcional que puede ocurrir durante la ejecución de un programa y que interrumpe el flujo normal de las instrucciones de nuestro programa.

Cuando curre un error dentro de un método, el método crea un objeto que encapsula este error y delega su manejo al sistema de ejecución. El objeto, llamado objeto de la excepción, contiene información acerca del error, incluyendo su tipo y el estado del programa cuando el error ocurrió. El crear un objeto de excepción y entregarlo al sistema de ejecución se conoce como Lanzar una excepción.

Después de que un método lanza una excepción, el sistema de ejecución intenta encontrar las instrucciones del programa que pueda manejarlo. Existe una lista ordenada donde se encuentran los métodos que han sido llamados, es en esta lista donde se buscará el método donde ocurrió el error y las instrucciones que puedan manejar este error. La lista de métodos es conocida como la pila de llamadas (ver la siguiente figura).

El sistema de ejecución busca en la pila de llamadas un método que contiene el bloque de código que puede manejar la excepción. Este bloque de código es llamado el manejador de la excepción. La búsqueda inicia con el método donde se origino el error y procede a recorrer la pila de llamadas en el orden inverso al que los métodos fueron llamados. Cuando un manejador apropiado es encontrado el sistema de ejecución le entrega el objeto y el control al manejador de dicha excepción. Un manejador de excepción es considerado apropiado si el tipo del objeto de excepción lanzado coincide con el tipo de excepción que puede ser manejado por el manejador.

Al hecho de elegir un manejador de excepción se le conoce como atrapar la excepción. Si el sistema de ejecución después de realizar una búsqueda exhaustiva de todos los métodos en la pila de llamadas y no encuentra un manejador adecuado para nuestra excepción, como se muestra en la siguiente figura, el sistema de ejecución y la propia aplicación pueden terminar su ejecución.

Usar excepciones para manejar errores tiene algunas ventajas sobre otras técnicas tradicionales de manejo de errores. Puedes conocer más sobre las ventajas de las Excepciones en esta entrada.