domingo, 2 de junio de 2013

Manejo de Excepciones en Java

Vamos a hablar un poco sobre las Excepciones en Java, que son?, de donde vienen? y como evitarlas entre, otras....... debemos tener presente que siempre estamos propensos a encontrarnos con errores o Excepciones cuando estamos desarrollando, por eso de la importancia de conocerlas y saber como tratarlas....

Básicamente una excepcion es un Objeto descendiente de la clase java.lang.Object, podemos pensar en ellas como una condición excepcional en nuestro sistema el cual altera la correcta ejecución del mismo, las excepciones nos indican que hay algo anómalo,  inconsistente o simplemente un Error, lo cual impide que el sistema se ejecute como debería de ser...

Tal vez se preguntaran si ¿pero Anómalo, inconsistente o Error no es básicamente lo mismo?...... podría ser, pero en este enfoque no necesariamene lo es, ya que lo que vamos a conocer como una excepcion no siempre es un error (hablando como excepcion en general, ya que en java una Exception es muy diferente a un Error), muchas veces necesitaremos trabajar con excepciones controladas para indicar alguna inconsistencia en nuestro sistema que podría provocar errores.......

A modo de ejemplo, podemos encontrarnos con el famoso NullPointerException el cual nos indica que un objeto se encuentra vació, pero esto no es un error ya que nosotros podemos trabajar con objetos null, entonces veamoslo como si la excepcion nos dijera "Es un objeto nulo y no se puede efectuar el proceso", mientras que hay errores como NoClassDefFoundError el cual nos indica que la maquina virtual de Java (JVM) no puede encontrar una clase que necesita, debido a por ejemplo que no encuentra un .class, esto si se maneja como un error en java

Para hacer mas claridad sobre el tema veamos la Jerarquía de Excepciones de Java (puede que no se encuentren algunas excepciones, pero se contemplan las mas comunes)

Jerarquía de excepciones



Vemos que se tiene un claro árbol de herencia mediante el cual se pueden definir las categorías de Excepciones o de Error que se puede dar en el sistema.

La importancia de Prever!!!

Cuando se esta programando debemos tener claro que nuestro código no es perfecto, así tengamos mucha experiencia en desarrollo siempre esta la posibilidad de que algo falle, sea por nuestro código o por otros factores, por eso de la importancia de contemplar todo desde antes, posibles fallos o lo que pueda afectar el sistema.

Veamos un ejemplo Simple:
private void metodoDividir(int dividendo, int divisor){
  
   String resultado+=dividendo/divisor;
   System.out.println(resultado);
  
}

el metodoDividir(int, int) teóricamente esta bien, claro, a simple vista si tenemos : dividendo = 4 y divisor = 2 pues el resultado es 2 ......básico....... pero y si el divisor es 0? pues con ese caso puntual el resultado seria el siguiente.




Vemos que nos indican que se produjo una ArithmeticException debido a una división por cero, además se muestra cual fue la traza del error pasando por el método main hasta el metodoDividir().


La anterior es una Excepcion simple, algo que se supone no debería pasar, es obvio, no se puede dividir por cero, o ¿no?.........pues no, en programación no podemos asumir ni pensar así, ya que muchas veces nos olvidamos de las cosas obvias y las pasamos por alto, el problema es que eso tan obvio puede detener toda la ejecución del programa.


Trabajando con try - catch - finally

con los bloques Try - Catch podemos capturar y procesar una posible excepcion, evitando que el sistema se detenga sin necesidad cuando el motivo de esto puede ser corregido facilmente, la estructura básica es la siguiente.
try {
  //Bloque de código que vamos a procesar
} catch(excepcion) {
  //Tratamiento que se le da a la posible excepción
} finally {
  //Bloque de código que se ejecutará despues del try o del catch
}


Apliquemos esto a nuestro ejemplo anterior...
private void metodoDividir(int dividendo, int divisor){
String resultado="";
 try {
   resultado+=dividendo/divisor;
  }catch (Exception e) {
   resultado="Se intentó dividir por cero";
   JOptionPane.showMessageDialog(null,"Error: No se puede dividir por cero ",
      "Advertencia",JOptionPane.WARNING_MESSAGE);
 }
   finally{
    System.out.println("Termino el proceso : el resultado es = "+resultado);
   }
}

Como vimos aplicamos la estructura de los bloques y de esta manera nos aseguramos que la excepción anterior fue controlada evitando que el sistema se detenga, en el catch podemos hacer el proceso que consideremos conveniente, ya sea solo informar del error o solicitar nuevos parámetros de entrada.

la salida es la siguiente:



Algunas Consideraciones.

Veamos un poco mas lo que debemos tener en cuenta cuando usamos estos bloques:

try : Aquí vamos a escribir todo el bloque de código que posiblemente llegue a lanzar unas excepción la cual queremos manejar, aquí va tanto el código como llamados a métodos que puedan arrojar la excepción.

En este bloque solo se detectara la primera excepcion lanzada, hay que tener en cuenta que por cada try se debe especificar un catch y/o un finally.

catch : en caso de que en el try se encuentre alguna excepción, se ingresara automaticamente al bloque catch donde se encontrara el código o proceso que queremos realizar para controlar la excepción.

Se pueden especificar cualquier cantidad de catch de ser necesario, estos deben ser ubicados después del try y antes del finally (en caso de que este ultimo se especifique),  cada catch que se ponga debe manejar una excepcion diferente (no se puede repetir) y el orden de estos depende de la jerarquía de herencia que se tenga, ingresando al primer catch que pueda suplir la necesidad a corregir, por ejemplo.
try {
      //Sentencias con posibles errores;
    } catch(InterruptedException e){
      //manejo de la exepcion
    } catch(IOException e){
   //manejo de la exepcion
    } catch(Exception e){
   //manejo de la exepcion
    }

Si se genera una excepción en el try, se valida a cual de los 3 catch se ingresa, dependiendo si InterruptedException puede controlarlo se ingresa a esa, sino entonces a IOException o si no a la superClase que seria Exception (ver la jerarquía de herencia anterior).

En el ejemplo que del metodoDividir() trabajamos directamente con Exception e, de esta forma nos aseguramos que capture cualquier excepción, sin embargo se recomienda usar la jerarquía en los catch para poderle dar un mejor manejo.

finally : Este bloque es opcional, lo podremos si queremos ejecutar otro proceso después del try o el catch, es decir, siempre se ejecutara sin importar que se encuentre o no una excepción.


Conclusiones.

Esta entrada es un abrebocas de lo que son el manejo de excepciones, ya que un solo post no es suficiente para todo lo que tiene que ver con ellas, quedan pendiente definir aspectos como checked y unchecked (ya que aquí esto se trabajo de forma muy general) o la forma de crear nuestras propias excepciones, propagación, clausulas throws entre otras.

En general vimos la importancia de controlar excepciones ya que eso hace parte de la seguridad y calidad de nuestros desarrollos, mas adelante se irán vinculando en otros post el uso de las mismas.........


Referencias.

Revista JavaWorld
SCJP Sun Certified Programmer for Java 6


También te podría Interesar. 


¿Hay algo que quieras anexar o comentar sobre esta entrada?  no dudes en hacerlo.....y si te gustó, te invito a compartir y Suscribirte ingresando al botón "Participar en este sitio" para darte cuenta de mas entradas como esta ;)

10 comentarios:

  1. Hola, deberias usar un "e.getMessage()", de esa forma obtenes un mejor resultado de la excepcion producidad.

    El metodo dividir podria ser:
    public static float Dividir(float a, float b) {

    float resultado = 0;
    try {
    resultado = a / b;
    } catch (Exception e) {
    System.out.println(e.getMessage());

    } finally {
    return resultado;
    }

    }
    **de esta forma al dividir por cero obtenes un "Infinity". Saludos

    ResponderEliminar
    Respuestas
    1. Hola, si señor tienes toda la razón, solo que muchas veces el e.getMessage() no solo arroja el tipo de error sino que arroja toda la traza en consola, que es muy importante al momento de saber exactamente que pasa, aunque también es recomendable poner uno o mas catch dependiendo de la excepcion que queramos controlar, muchas veces si sabemos realmente que tipo de error va a salir entonces ahi no seria tan necesario el e.getMessage(), por eso en este caso no lo puse ya que sabia que tipo de excepcion saldria.

      Un saludo y gracias por comentar.

      Eliminar
  2. Hola Cristian.

    Excelente la motivacion para construir un blog. Para el caso de las excepciones en Java, le referencio dos entradas que construi en mi blog acerca de como capturar las excepciones y manejarlas de forma global para una aplicacion. Aqui estan los enlaces que pueden ser de interes:

    http://javaadvance.blogspot.com/2013/10/java-se-swing-exception-handling.html
    http://javaadvance.blogspot.com/2013/08/java-server-faces-exception-handler.html

    ResponderEliminar
    Respuestas
    1. Daniel me alegra verlo por aquí, ya vi el blog y muy interesante, un saludo y gracias por el aporte ;)

      Eliminar
  3. Excelente aporte de conocimientos, se agradece.

    ResponderEliminar
  4. A no ser que queramos manejar una excepción por algún motivo, es mejor propagarla que capturarla, centrándonos en la lógica de nogocio y no en la gestión de excepciones, eso mejor hacerlo en la capa de controllers.
    Desacoplar lógica de negocio de capa de presentacion, en tu ejemplo usas componentes de la vista () dentro de un bloque catch dentro de un componente de lógica de negocio.
    Saludos,
    David

    ResponderEliminar
    Respuestas
    1. Hola David, como puedes darte cuenta la entrada es básica como muchas de las que hay aquí, obvio hay temas que pueden ser mucho mas complejos pero en este caso estoy manejandolo a modo de introducción..... gracias por comentar.

      Eliminar
  5. Un bloque finally SIEMPRE se ejecuta,
    Haya o no sentencias return
    Saludos,
    David

    ResponderEliminar
    Respuestas
    1. Hola David, tienes razón, gracias por hacerme caer en cuenta del error, ya lo actualicé.... un saludo.

      Eliminar
  6. Buenos días me pueden ayudar con estas dos preguntas y no entiendo mucho.Gracias por su tiempo.

    1)Escoger tres Exceptions y buscar en que caso surgen estas Exceptions(En java)
    2)Traer Tres preguntas de excpeciones que encuentre por internet

    ResponderEliminar

Eres libre de realizar cualquier comentario, desde que pueda ayudar con gusto lo atenderé, y si es un critica, bienvenida sea!!!