miércoles, 5 de diciembre de 2012

Excepciones parte 2: Excepciones No Marcadas

Buenas amigos, vamos a continuar con el tema de las excepciones. Como ya dijimos anteriormente, he dividido el tema de las Excepciones en 3 partes para hacerlo más a meno. Anteriormente hice la parte uno, "Excepciones Parte 1: Definición y Excepciones Marcadas." ahora proseguiremos con la parte 2 o "Excepciones No Marcadas"


Las excepciones No Marcadas pertenecen al grupo de "RunTimeException y sus subclases".  Este tipo de Excepción no son obligatorias de capturar, ya que el que ocurra es debido a que no hemos programado bien, por lo que no debe ser una opción capturarlas, si no determinar donde está el error y solucionarlo.Aún así, es posible que nos tropecemos con alguna situación que requiera capturar este tipo de excepción.

Cuando un programa produce una excepción, produce un volcado de pila por consola con los datos de la excepción, entre ellos la clase y la linea de código donde se produce la excepción:


Teniendo la anterior imagen, si nosotros lo ejecutamos nos dará una excepción, ya que no se puede dividir un número entre 0:


Podemos observar que se nos muestra el tipo de excepción que produce, la clase donde se produce y la linea de código donde se produce. Teniendo esta información deberíamos ir a la linea de código en cuestión y solucionar el problema en vez de capturar la excepción, pero como ya he dicho, hay situaciones en la que requiere capturar este tipo de excepciones. En el ejemplo anterior no se da el caso, en vez de capturar, deberíamos solucionar.

Tras mostrarnos el volcado de pila, la ejecución de programa finaliza. Imaginemos que no queremos que finalice, que queremos por todos los medios capturar esa excepción. Para ello utilizaremos los bloques try,catch y finally:

        • try{

        • //instrucciones de las que queremos capturar la excepción...

        • }catch(tipoExcepcion arg){

        • //Instrucciones a realizar cuando surja la excepción

        • }finally{

        • //instrucción final

        • }
La palabra clave "try" delimita el inicio de las instrucciones cuya excepción queremos capturar. TODA instrucción a la que se desee capturar una excepción debe ir dentro del bloque "try". Como podéis observar, escribo "try" y abro llaves, escribo las instrucciones y cierro llaves.
        • try{
        • //instrucciones
        • }
El bloque "catch" nos permite definir las instrucciones a realizar en caso de que ocurra una excepción. Previamente deberemos poner en la lista de argumentos del "catch" el tipo de excepción que queremos capturar.
        • catch(tipoExcepción arg){
        • //Instrucciones
        • }
Existen algunas directrices que tenemos que tener en cuenta a la hora de manejar bloques "catch":
    • Se pueden crear tantos bloques "catch" como sean necesarios.
    • No pueden haber 2 bloques "catch" con la misma excepción.
    • Aunque se tengan varios "catch" que puedan llegar a capturar la misma excepción, solo una se ejecutará.
      • Supongamos que tenemos capturadas 2 excepciones:
          • catch(NullPointerException npe){
          • //Instrucciones
          • }
          • catch(RunTimeException rte){
          • //Instrucciones
          • }
      • Tenemos estos 2 "catch" con sus excepciones, como habréis visto en la parte 1, "NullPointerException" es una subclase de "RunTimeException", si tuviésemos una instrucción y al ejecutarse salta la excepción, al tener 2 excepciones que hacen referencia a una misma situación, solo una de las 2 se ejecutará, en este caso la primera que encuentra, "NullPointerException".
    • En el caso de que existan varios "catch" con excepciones relacionadas por herencia, los "catch" más especifico deben estar SIEMPRE por delante o el programa no compilará
      • Volviendo a los 2 "catch" de las lineas anteriores, podéis observar que pongo primero la excepción "NullPointerException" y posteriormente "RunTimeException". Esto no lo he hecho por que sí, ya que cuando tu declaras la excepción "RunTimeException" en el "catch" le indicas que se puede dar cualquier subclase de esta, algo muy genérico  mientras que en el otro "catch" he sido más específico y le he indicado que quiero capturar exactamente esa subclase, "NullPointerException". Por lo tanto al crear los 2 "catch" con sus excepciones, he puesto la primera "NullPointerException" por ser más específica.
    • Los bloques "catch" son opcionales, si disponemos de un bloque "finally" podemos prescindir de los bloques "catch". Pero en caso de que no exista un bloque "finally" (también son opcionales) deberemos poner obligatoriamente un bloque "catch".

Como ya mencione unas lineas atrás, el bloque "finally" es opcional. 
      • finally{
      • //Instrucciones
      • }
Este bloque, si está, se ejecutará SIEMPRE, haya una excepción o no. La única forma de que no se ejecute el bloque "finally" es cerrando la aplicación antes de llegar a él con el siguiente comando:
      • System.exit(0);
Esta linea produce el cierre total de la aplicación , con lo cual es imposible ejecutar el "finally". SIEMPRE se ejecuta.

Voy a poner el ejemplo que puse al principio con la división entre 0 capturada:

Bien, tenemos la excepción capturada, cuando ejecutemos este código, ya no terminará la ejecución del programa, saltará la excepción y ejecutará la instrucción que corresponda, en este caso nos mostrará por consola el mensaje de que se está dividiendo por 0, posteriormente ejecutará el bloque "finally". Una vez realizado esto la JVM seguirá leyendo lineas de código y ejecutándolas  como la siguiente linea de código que hay después del "finally" es que nos muestre por pantalla el valor almacenado en la variable res, que es 0, ya que no ha podido hacer la división de 5 entre 0 y el valor inicial de la variable, es 0.


Bien amigos, hasta aquí las excepciones No Marcadas, espero que no se hagan un lío  es importante saber esto. En la parte final de las excepciones, veremos la personalización de una excepción y definiré algunas de las excepciones más usadas.

Un saludo.


1 comentario:

  1. Bua esta pagina vale oro : ))
    DIRECTA A FAVORITOS XD.
    Mil gracias por las explicaciones me vinieron de lujo.

    ResponderEliminar