viernes, 18 de mayo de 2012

Excepciones


Definición

           
Una excepción que no fue capturada correctamente hace que el sistema se caiga. Una excepción es un evento que ocurre durante la ejecución de un programa, que interrumpe el flujo normal de ejecución.
                Java usa excepciones para el manejo de errores, error handling. Es un sinónimo de eventos excepcionales. Un buen manejo de Excepciones hace a un sistema robusto y estable, confiable.



Bloque try, catch y finally

                Dentro del bloque try se pondrá todo el código que puede arrojar alguna excepción. Los bloques catch son los encargados de atrapar las excepciones arrojadas por alguna sentencia del bloque try. El bloque finally se ejecuta siempre después del try y del catch, haya habido o no lanzada una excepcion.

                Ejemplo:

        try {
            ....
        }
        catch (ArrayIndexOutOfBoundsException aioobe) {
            ....
        }
        catch(Exception e){
            ....
        }
        finally{
            ....//Limpieza de codigo
        }



Tipos de Excepciones

-Excepciones No Chequeadas (Unchecked Exceptions)


                Son las excepciones que tienen como superclase a la clase RuntimeException. No hay necesidad de capturarlas, es decir que no se necesita utilizar el bloque try/catch, pero al saltar uan excepción de este tipo, como todas las excepciones corta el flujo de la ejecución.
                Pueden ser difíciles de detectar, pero finalmente hacen que el sistema se caiga si no fueron tomadas en cuenta.

                Ejemplo:
               
                Cuando se realiza una división por  cero se lanza automáticamente una ArithmeticException. Cuando se quiere acceder a un objeto que apunta a null se lanza automáticamente una NullPointerException. Cuando se quiere acceder a un array con un índice que es mayor al tamaño del array, se lanza automáticamente una ArrayIndexOutOfBoundException.

                En java:

                                int unValor = 0; //Este valor se suponia que no podia ser Cero pero en algun momento se convirtio en Cero
                               try{
                                               int resultado = 10 / unValor;
                               }catch(ArithmeticException ae){
                                               //Acá tengo el control del flujo por el error de dividir por cero, asi informo al usuario que hubo un error.
                               }finally{
                                               //Y finalmente continuo con el sistema, reestableciendo el control.     
                               }


-Execpciones Chqueadas(Checked Exceptions)

                Son las excepciones que tienen como superclase a la clase Exception. Necesitan ser capturadas, caso contrario no se podrá compilar el código.
                En el caso del FileReader se esta accediendo a lo que se llama un recurso externo al sistema en si. El sistema consta de las variables, las clases, los packages y los métodos que definimos, pero un archivo es un recurso externo, es decir que puede no existir al momento de ejecutar nuestro programa, ose borrado mientras nuestro programa esta funcionando.
                También llamamos recurso externo a una conexión con la base de datos, porque depende de una conexión de red. Todos estos artefactos que no son parte del programa sino que se interactúa con ellos, pueden traer algunas complicaciones como, no existir, que la red no esta conectada, que no haya mas espacio en disco, que la red se caiga en medio de una corrida del programa.
                Todos estos motivos llevan a la necesidad de evaluar si se pueden realizar correcta y completamente las instrucciones del programa. Por lo tanto si algo sale mal, lo que no puede ocurrir es que dejemos una conexión tomada, o un archivo sin que otro sistema pueda acceder a el.
                Aquí es donde tenemos que prestar mucha atención para que nuestro sistema no traiga problemas, simplemente verificar en el finally que se han liberado los recursos.

                Ejemplo:

                La clase FileReader se utiliza para el acceso al disco. Cuando utilizo un acceso a disco con métodos de la clase FileReader, debo capturar la excepción IOException.

                En java:

                               FileReader archivoALeer = null;
                               String nombreDelArchivoEnAcceso = “archivo.txt”;

                               try{
                                               archivoALeer = FileReader(new File (nombreDelArchivoEnAcceso));
                                               //Acá intento hacer lo que tenga que hacer con el archivo
                               }catch(IOException ioe){
                                               //Acá informo que ocurrió un error de acceso al recurso externo.
                               }finally{
                                               if (archivoALeer != null){
                                                               try{
                                                                              archivoALeer.close();
                                                               }catch (Exception e){
                                                               }
                                               }
                               }

La sentencia “throw”

La sentencia throw se usa para lanzar excepciones. Requiere un único argumento, una instancia de la clase java.lang.Throwable, que es implementada por la clase Exception y errores.

Ejemplo:

boolean hayError = true;
     if(hayError) {
                throw new Exception();
     }

Esto significa que después de evaluar la clausula hayError y al ver que es verdadero, significa que debe cortarse el flujo de corrida del programa, y desde el método que llama a este método debe capturarse este error con un bloque try/catch, e  informar al usuario que ocurrió el error y luego restablecer el sistema.

Creacion de excepciones propias

Por convención su nombre debería terminar con la palabra Exception. Consiste en crear una clase que hereda de java.langException. Lo conveniente es ir identificando que tipo de excepciones, en el flujo de información de la vida real, pueden ser representadas por una excepción creada a medida, de forma tal de poder entender de forma inmediata un bloque de código.
El manejo de excepciones hace que el código sea legible y fácilmente comprensible.

Ejemplo:

public class MiExepcionException extends Exception{
        //Acá va la definición de la clase.
    }

La keyword Throws

La palabra clave throws se utiliza en la firma de los métodos que pueden lanzar excepciones. Una buena combinación de Creación de Excepciones propias del negocio que estamos modelando con el sistema, y la declaración en los métodos indicados que pueden lanzar este tipo de excepciones, hace que sea fácil programar y compartir clases entre distintos equipos de desarrollo.
Estas practicas facilitan mucho el compartir código y queda uno siempre obligado a capturar excepciones que permiten un buen control del flujo de datos dentro del sistema, y lo hacen robusto.

Ejemplo:

                public class Hombre{
                              
                               public void comer () throws MiExcepcion{
                              
                               //Acá va algo de código.

                               //Acá debemos evaluar una condición que hace que arrojemos una excepción.
                               throw new MiExcepcion();
                               }
                }


Ejemplo Completo de todo  lo anterior

class NumeroNegativoException extends Exception {
NumeroNegativoException(){
super("El numero debe ser mayor o igual que 0");
}
}

static long Factorial(int n) throws NumeroNegativoException{

              if(n<=0) throw new NumeroNegativoException();

              int f=1;
              for(int i=1;i<=n;i++) f*=i;

              return f;
}

public static void main(String args[]){

              int i;
              BufferedReader entrada = new BufferedReader(
              new InputStreamReader(System.in));

              String s = new String();
              try{
              s=entrada.readLine();

              //Convertir la entrada en entero
              i = Integer.parseInt(s);

              System.out.println("Factorial de " + i + ": " + Factorial(i));

              } catch(NumeroNegativoException nne){
              //Mostrara "El numero debe ser mayor o igual que 0"
              System.err.println(nne.getMessage());
              } catch(IOException ioe){
              System.err.println("Se ha producido un error en la entrada de datos");
              } catch(NumberFormatException nfe){
              //Se lanza cuando la cadena “s” no se puede convertir a entero
              System.err.println("Formato erroneo");
              }catch(Exception e){
             
            System.err.println("Se ha producido un error");
              }
              }
              }


2 comentarios:

  1. Buenos días, tú blog esta muy completo, estoy siguiendo algunos temas, enhorabuena!

    ResponderEliminar
  2. Las excepciones chequeadas no necesitan ser capturadas, podrías no tratarlas ojo! La diferencia con las no chequeadas, es que al invocar un método sabes específicamente que excepciones arroja. Luego podes tratarlas como no.

    ResponderEliminar