sábado, 14 de julio de 2012

4.1.1. Introduccion a las excepciones


Excepciones


El término 
excepción se utiliza en Java cuando algo salió mal, es decir, cuando ocurrió un error. Como todos sabemos, existe un gran número de situaciones por las que el software puede fallar, pero si queremos hacer software de calidad, debemos tomar conciencia que las clases de aplicaciones o applets que desarrollemos, en Java, deben manejar las excepciones.

En Java una excepción es un objeto que define una situación inusual o un error.

Una excepción es entonces un evento que sucede con algún error, pero es algo que no debiera pasar, resulta en la lógica de la clase en la que ocurre, y debemos de cuidarnos de no cometer un error de lógica.
Normalmente Java nos detecta algunos errores en los que pudiera suceder una excepción y nos pide que declaremos el lugar en el que puede ocurrir, si es que no la manejaremos, entonces un programa puede estar diseñado para procesar las excepciones en tres formas distintas:
  •  No manejarla
  •  manejar la excepción cuando ocurre
  •  manejar la excepción en algún otro punto del programa
Una excepción tan sencilla se puede revisar en el siguiente ejemplo:
public class AplicacionExcepcion1 {
public static void main(String args[]) {
 System.out.println("Antes del error");
 System.out.println("Division por cero = " + 3 / 0);
 System.out.println("Despues del error");
}
}
En este ejemplo observamos como primero se despliega un letrero “Antes del error”, después se despliega un cálculo en el que sabemos que habrá un error y finalmente se despliega otro letrero “Después del error”.
Al ejecutar la aplicación anterior observamos lo que sucede:
Vemos como se despliega el letrero “Antes del error”, pero después observamos el error de ejecución denominado en Java una excepcion, la Arithmetic Exception, esta excepción sucede cuando tratamos de dividir un número por cero, por eso mismo no alcanzamos a ver el mensaje “Después del error”, ya que al haber error de ejecución, se termina de usar la aplicación.
Hay excepciones las cuales el compilador las marca desde un inicio y nos pide que nos protejamos para eso, por ejemplo la siguiente aplicación fue escrita para pedir un número al usuario y obtener el cuadrado de ese número:
import java.io.*;
public class AplicacionExcepcion1 {
public static void main(String args[]) {

 BufferedReader in =
  new BufferedReader(new InputStreamReader(System.in));
 int n;
 System.out.println("Da el numero");
 n = Integer.parseInt(in.readLine());
 System.out.println("El cuadrado del numero = " + n*n); }
}
Pero al compilar dicha aplicación observamos que no compila, el compilador manda el siguiente mensaje:
Nos está diciendo que al momento de tratar de leer un dato, puede haber un error de ejecución el cual debe ser capturado para que la aplicación no falle. Pero que tipo de error puede ocurrir, pues si se supone que  se pide un número y el usuario no da un número, sino un nombre, entonces habrá problemas con la aplicación y se terminará.
La aplicación se compila entonces marcando la excepción que puede lanzar de la siguiente manera:
import java.io.*;
public class AplicacionExcepcion2 {
public static void main(String args[]) throws IOException  {

 BufferedReader in =
  new BufferedReader(new InputStreamReader(System.in));
 int n;
 System.out.println("Da el numero");
 n = Integer.parseInt(in.readLine());
 System.out.println("El cuadrado del numero = " + n*n); }
}
Vemos que al declarar lo que está en repintado, la aplicación si compila, es decir, ahora si podemos ejecutarla tranquilamente, por ejemplo:
Pero si nos ponemos a analizar, la aplicación todavía puede fallar, es decir, ¿qué pasa si en lugar de un número entero le damos un número con decimales?
Vemos como da una excepción llamada NumberFortmatException, con el valor de 5.5
Por otra parte, ¿qué pasa si le damos letras en lugar de números?
Vemos como también nos da el error de excepción NumberFormatException, con el valor cinco.
Hasta ahora hemos visto las excepciones NumberFormatException y la de ArithmeticException, las cuales son clases que están definidas en Java que nos hablan de errores, todas las clases de excepción se derivan de la clase Trowable. Todos pensaríamos que Exception es la superclase de todas las clases de excepciones, pero no es así la super clase es Trowable. La clase Throwable tiene dos subclases: Error y Exception. Hay nueve subclases de la clase Exception ya predefinidas, y cada una de ellas, a su vez, tiene numerosas subclases:
Y a su vez esta clase Trowable desciende de la clase Object.
Las excepciones se pueden visualizar como se muestra a continuación:
¿Cómo es que se pueden arreglar estos errores de Ejecución?
La única manera de hacer que el software no tenga errores, es utilizando la instrucción try/catch, esta es la instrucción  en Java que nos permiten detectar y corregir estos errores, veamos primero el formato del try/catch:
try
{
    instrucciones que pueden lanzar una excepción
}
catch (Excepción1 e1)
{
    instrucciones para el error 1
}
catch (Excepción2 e2)
{
    instrucciones para el error 2
}
finally //  bloque  opcional
{
    instrucciones que se hacen se haya encontrado error o no
}
La cláusula catch comprueba los argumentos en el mismo orden en que aparezcan en el programa. Si hay alguno que coincida, se ejecuta el bloque y sigue el flujo de control por el bloque finally (si lo hay) y concluye el control de la excepción.
Si ninguna de las cláusulas catch coincide con la excepción que se ha producido, entonces se ejecutará el código de la cláusula finally (en caso de que la haya). Lo que ocurre en este caso, es exactamente lo mismo que si la instrucción que lanza la excepción no se encontrase encerrada en el bloque try.
Ejemplo:
Supongamos que juntamos instrucciones que pueden tener mas de un error, como pedir dos numeros y dividir el primero entre el segundo, ya sabemos que al pedir un número, podemos tener un error con la excepción de NumberFormatException, y que al dividir un número por otro podemos tener el error de ArithmeticException, entonces juntando estos dos errores, podemos tener la siguiente aplicación:
import java.io.*;
public class AplicacionExcepcion3 {
public static void main(String args[]) throws IOException  {

 try {
  BufferedReader in =
   new BufferedReader(new InputStreamReader(System.in));

  int n1, n2, n;
  System.out.println("Da un numero");
  n1 = Integer.parseInt(in.readLine());
  System.out.println("Da otro numero");
  n2 = Integer.parseInt(in.readLine());
  System.out.println("La division = " + n1/n2);
 }
 catch (NumberFormatException nfe) {
  System.out.println("Numero invalido " + nfe.toString());
 }
 catch (ArithmeticException ae) {
  System.out.println("Division invalida " + ae.toString());
 }
}
}
Observamos de esta aplicación que las instrucciones completas están en el try, y de estas instrucciones pueden suceder dos diferentes errores de excepción, la que tengamos un número que es inválido o que tengamos una división por cero. En este ejemplo vemos que la parte de finally de la instrucción try/catch no fue usado, porque es opcional.
Pero pudimos haberlo utilizado, para desplegar algún mensaje de despedida o alguna otra instrucción, veamos como queda la ejecución con errores:
Aquí observamos como al tratar de dar el segundo número obtuvimos mensaje de error.
Aquí nos damos cuenta que al dar el cero y tratar de hacer la división nos da el error de la excepción aritmética.
Si quisiéramos que el programa no terminara podemos utilizar un ciclo para repetir mientras que el usuario haya dado datos incorrectos, haciendo uso de una variable boleana:
import java.io.*;
public class AplicacionExcepcion4 {
public static void main(String args[]) throws IOException  {

 boolean error = true;  //asumimos que hay error

 while (error) {  
  try {
   BufferedReader in =
    new BufferedReader(new InputStreamReader(System.in));

   int n1, n2, n;
   System.out.println("Da un numero");
   n1 = Integer.parseInt(in.readLine());
   System.out.println("Da otro numero");
   n2 = Integer.parseInt(in.readLine());
   System.out.println("La division = " + n1/n2);
   error = false;   // al llegar aqui no hubo error
  }
  catch (NumberFormatException nfe) {
   System.out.println("Numero invalido " + nfe.toString());
  }
  catch (ArithmeticException ae) {
   System.out.println("Division invalida " + ae.toString());
  }
 }
  
}
}

No hay comentarios:

Publicar un comentario