sábado, 26 de noviembre de 2011

Manejo de Excepciones en Java

votar
Una excepción se produce cuando una condición excepcional interrumpe o altera el curso normal de un programa. Por ejemplo, un método que debe abrir un archivo se encuentra con que tal archivo no existe, o se intenta realizar una división siendo el divisor cero.

El manejo de excepciones consiste en escribir el código necesario para capturar una excepción y resolverla o al menos informar al usuario de lo que ocurre y que no se asuste. No es lo mismo ver una ventanita que nos informa amablemente de que no se encuentra el archivo o que inserte un disco a que la aplicación se quede muerta o ver un galimatías de números y letras (recordemos que el usuario final no suele ser un programador).

Como en Java todo se reduce a objetos, cuando ocurre una excepción el método que la provoca crea un objeto con información sobre el error y el sistema busca algo en el programa para manejarlo. Estos objetos, por supuesto, tienen que pertenecer a una clase. En Java, las excepciones derivan todas de la superclase Throwable, que está en el paquete java.lang. Throwable significa "arrojable" o "lanzable" en inglés, porque en Java las excepciones se "lanzan" o "arrojan" y hay que "pillarlas" o manejarlas con un gestor de excepciones (exception handler). De Throwable derivan las clases Error y Exception, y de esta última deriva la clase RuntimeException, cuyos objetos son errores que se producen en tiempo de ejecución.

Las excepciones pueden producirse por fallos de programación o por fallos imprevisibles del sistema. Estos últimos son los que forman la clase Error, de la que el sistema no se espera que se recupere y por eso no se requiere que se manejen. Vamos, que si te has quedado sin memoria, se va a ir todo a la porra hagas lo que hagas.

Entre las subclases de Error tenemos IOError, AWTError, CoderMalfunctioError, AssertionError, VirtualMachineError o mi favorita: ThreadDeath, que parece el título de una película. Pero hay muchas más.

Una de las grandes controversias en Java es que obligatoriamente hay una serie de excepciones que hay que manejar, quieras o no. Unos lo ven innecesario, otros imprescindible. Nosotros no vamos a mojarnos, sólo a explicar en qué consiste eso.

Las checked exceptions, o excepciones revisadas son las que derivan de la clase Exception, menos RuntimeException. Son las que se supone que hay que prever y de las que la aplicación se puede recuperar. Si no las manejas o las declaras, no podrás compilar tu programa.

Esto se hace de la siguiente manera: un método que pueda lanzar una excepción, bien lo hayas escrito tú, bien esté en el API, debe declararlo así
      public void miMétodoArriesgado() throws NombreDeLaExcepción;

Después, al utilizar ese método en el programa, hay que hacerlo dentro de un bloque try-catch (prueba y captura), que básicamente viene a decir: prueba a usar este método, y si produce una excepción, captúrala y haz lo que debas con ella. 
      try{
         public void miMétodoArriesgado(); //método que puede producir una excepción
      }catch (NombreDeLaExcepción e){
            //código que indica qué hacer si se produce
      }

Por supuesto, si la excepción no se produce, el código que escribimos dentro de catch no se ejecutará, si no que el programa seguirá normalmente. Además, si queremos que algo se ejecute independientemente de que surja o no una excepción, escribimos finally después de catch. Todo lo que va dentro de finally se ejecuta siempre, así que es muy útil para atar cabos sueltos, como cerrar archivos, etc.

Si no queremos usar un bloque try-catch para manejar la excepción, siempre nos queda la opción de esquivarla. Esto es como si alguien te lanza una pelota y tú te agachas con la esperanza de que otra persona la coja. Porque en alguna parte del programa, "alguien", léase un método, tiene necesariamente que pillar la excepción. El sistema va de método en método, hasta llegar a main() si hace falta, buscando un bloque de código que se ocupe de manejarla. Personalmente, esquivar la excepción no me gusta demasiado. Creo que es mejor lidiar con ella cuanto antes y listo. Pero a veces, por necesidades de programación, es mejor dejarla pasar y que otro método se ocupe. En ese caso hay que declarar el método como vimos, especificando la excepción que lanza.

Como sublcases de Exception tenemos IOExcepton, SQLException, ApplicationException, AWTException, BadLocationException, unas cuantas (muchas) más que hay en la librería Java y todas las que se te puedan ocurrir para tus métodos arriesgados. Porque por supuesto tú puedes crear tus propias excepciones.

Por último, están las RuntimeException y sus subclases, que como ya comentamos, no son excepciones revisadas, sino unchecked, es decir, no se revisan en el momento de la compilación. Estas excepciones tienen en común con las de clase Error que no se pueden anticipar ni normalmente recuperar de ellas, pero al contrario que estas, no se producen por fallos de sistema, sino casi siempre por fallos de programación, como errores de lógica. No es necesario declarar ni manejar estas excepciones, pero puedes hacerlo si quieres.

Dentro de RuntimeException podemos encontrar ArithmeticException,CannotRedoException, CannotUndoException,NullPointerException,NumberFormatException,ClassCastException,IndexOutOfBoundsException o BufferOverflowException. Pero claro, hay muchísimas más.

Si quieres dejar algún comentario o pregunta, ya sabes como ;)

  

   

4 comentarios:

  1. podría poner ejemplos sencillos de la diferencia de las excepciones Runtime y las que no lo son

    ResponderEliminar
  2. Hola Anónimo.
    Una RuntimeException se produce durante el tiempo de ejecución debido a un fallo de tu código, por ejemplo, si intentas hacer esta división:
    int i = 5/0;
    se produciría una ArithmeticException, y si intentas acceder al elemento número 6 de un array, cuando tú sólo has creado un array de 4 elementos, se produce un ArrayIndexOutOfBoundsException.
    En cambio, las otras excepciones no se producen por fallos de lógica en tu código, sino por otra circunstancia. Por ejemplo, ClassNotFoundException sucede cuando la JVM no puede cargar una clase porque no la encuentra, y esto puede ser porque algo le ha pasado a la clase o porque hayas escrito mal su nombre en la línea de comandos (a mí me sucede a menudo), pero no porque haya algún fallo en tu código.
    Por último, las excepciones de la clase Error están mayoritariamente formadas por fallos del sistema, pero hay que tener en cuenta, aunque resulte algo confuso, que esos fallos de sistema pueden estar causados por errores en el código.
    Por ejemplo, si escribes un método que produce un bucle infinito como éste:
    public void repiteEsto(){
    System.out.println("Chicos, no hagáis esto en casa");
    repiteEsto();
    }
    Este método es recursivo y se repetirá una y otra vez hasta que desborde al stack y se lance un StackOverflowError.
    Espero que esta explicación te haya servido de ayuda.;-)

    ResponderEliminar
  3. gracias por la explicacion sigue publicando..

    ResponderEliminar