jueves, 12 de noviembre de 2015

MANEJO DE EXCEPCIONES EN JAVA

La palabra excepción indica una irregularidad en el software que se inicia en alguna sentencia del código al encontrar una condición anormal; no se debe confundir con una excepción hardware. Una excepción es un error de programa que sucede durante la ejecución; si al ocurrir está activo un segmento de código denominado manejador de excepción, entonces el flujo de control se transfiere al manejador; si no existe un manejador para la excepción, ésta se propaga al método que invoca, si en este tampoco se capta, la excepción se propaga al que a su vez le llamó; si llega al método por el que empieza la ejecución, es decir, main() y tampoco es captada, la ejecución termina.
En general, el mecanismo de excepciones en Java permite:
a) Detectar errores con posibilidad amplia de recuperación.
b) Limpiar errores no manejados.
c) Evitar la propagación sistemática de errores en una cadena de llamadas dinámicas.
Mecanismo del manejo de excepciones en Java
El modelo de un mecanismo de excepciones consta fundamentalmente de cinco nuevas palabras reservadas: try, throw, throws, catch y finally.
1.      Try es un bloque para detectar excepciones.
2.   Catch es un manejador para capturar excepciones de los bloques try,
3.   Throw es una expresión para levantar (raise) excepciones,
4.   Throws indica las excepciones que puede elevar un método,
5.   Finally es un bloque opcional situado después de los catch de un try.
Los pasos del modelo son:
1. Establecer un conjunto de operaciones para anticipar errores; esto se realiza en un bloque try.
2. Cuando una rutina encuentra un error, lanzar una excepción; el lanzamiento (throwing) es el acto de levantar una excepción.
3. Para propósitos de limpieza o recuperación, anticipar el error y capturar (catch) la excepción lanzada.
El mecanismo de excepciones se completa con:
Un bloque finally que, si se especifica, siempre se ejecuta al final de un try;

Especificaciones de excepciones que dictamina cuáles, si existen, puede lanzar un método.
Bloques try
Ya se mencionó que un bloque try encierra las sentencias que pueden lanzar excepciones y que comienza con la palabra reservada try seguida por una secuencia de sentencias de programa encerradas entre llaves; a continuación del bloque  hay una lista de manejadores llamados cláusulas catch. Al menos un manejador catch debe aparecer inmediatamente después de un bloque try, si no hay tal manejador, debe especificarse el manejador opcional finally. 
La sintaxis del bloque try es:
try                              
{
   código del bloque try 
 }
 catch (signatura)
 {
   código del bloque catch
 }
Clases de excepciones definidas en Java
En su empeño por estandarizar el manejo de excepciones Java declara un amplio con junto de clases de excepciones, las cuales forman una jerarquía en la que la base es Throwable, que deriva directamente de la superclase base Object.
 De Throwable derivan dos clases: Error y Exception; las excepciones del tipo Error son generadas por el sistema, se trata de errores irrecuperables y es extraño que se produzcan; por ejemplo: salir de la memoria de la máquina virtual; por tanto, de producirse una excepción Error se propagará hasta salir por el método main(); los nombres de las subclases que derivan de dicha excepción acaban con el sufijo Error, como InternalError o NoClassDefFoundError. De Exception derivan clases de las que se instancian objetos (excepciones) para ser  lanzados; pueden ser capturados por los correspondientes catch; las clases derivadas de  Exception se encuentran en los diversos paquetes de Java, todas tienen como nombre un identificador que indica su finalidad, terminado en Exception; la jerarquía de excepciones a partir de esta base es la que se muestra en la figura.

EJEMPLO:
Cálculo de las raíces o soluciones de una ecuación de segundo grado. Una ecuación de segundo grado, tiene dos raíces: 
Los casos de indefinición son: 1) a = 0 ; 2)  b2 – 4ac <0, que no producen raíces reales, sino imaginarias; en consecuencia, se consideran  dos excepciones: NoRaizRealException y CoefAceroException
La clase EcuacionSegGrado tiene como atributos a, b y c, que son coeficientes de la ecuación; además, r1, r2 son las raíces; el método raices() las calcula, su declaración es:
void raices() throws NoRaizRealException, CoefAceroException
El cuerpo del método es:
void raices() throws NoRaizRealException, CoefAceroException
{
  double discr;
  if(b*b < 4*a*c)
    throw new NoRaizRealException("Discriminante negativo",a,b,c);
  if(a == 0)
    throw new CoefAceroException("No ecuaciones De segundo grado  ",a,b,c);
  discr = Math.sqrt(b*b - 4*a*c);
  r1 = (-b - discr) / (2*a);
  r2 = (-b + discr) / (2*a);
}
raíces() lanza excepciones si no tiene raíces reales o si el primer coeficiente es cero; el método no captura excepciones sino que se propagan; es necesaria la cláusula throws con los tipos NoRaizRealException, CoefAceroException. El método desde el que se llame a raices() debe tener un bloque try-catch para capturar las excepciones lanzadas o se propagarán, lo que exige de nuevo la cláusula throws. La siguiente aplicación define las clases con las excepciones antes mencionadas; en el método main() se piden los coeficientes de la ecuación, se crea el objeto, se llama al método de cálculo y se escribe en pantalla.
import java.util.*;
// representa la excepción: ecuación no tiene solución real
class NoRaizRealException extends Exception
{
  private double a,b,c;  
  public NoRaizRealException(String m, double a, double b, double c)
  {
    super(m);
    this.a = a;
    this.b = b;
    this.c = a;
  }
  public String getMessage()
  {
   return  "Para los coeficientes "+(float)a +", " +(float)b + ", " +(float)c +super.getMessage();
  }
}
// representa la excepción: no es ecuación de segundo grado
class CoefAceroException extends Exception
{
  public CoefAceroException(String m)
  {
    super(m);
  }
}
// clase para representar cualquier ecuación de segundo grado
class RaiceSegGrado
{
  private double a,b,c;
  private double r1,r2;   
  public RaiceSegGrado(double a, double b, double c)
  {
    this.a = a;
    this.b = b;
    this.c = c;
  }
  public  void raices() throws NoRaizRealException, CoefAceroException
  {
    ...
  }
  public  void escribir()
  {
    System.out.println("Raices de la ecuaci¢n; r1 = "+ (float)r1 + "  r2 = " + (float)r2);
  }
}      
// clase principal
public class Raices
{
  public static void main(String [] ar)
  {
    RaiceSegGrado rc;
    double a,b,c;
    Scanner entrada = new Scanner(System.in);
    // entrada de coeficientes de la ecuación
    System.out.println("Coeficientes de ecuación de segundo grado");
    System.out.println(" a = ");
    a = entrada.nextDouble();
    System.out.println(" b = ");
    b = entrada.nextDouble ();
    System.out.print(" c = ");
    c = entrada.nextDouble();
    // crea objeto ecuación y bloque para captura de excepciones
    try
    {
      rc = new RaiceSegGrado(a,b,c);  
      rc.raices();
      rc.escribir();
    }
    catch(NoRaizRealException er)
    {
      System.out.println(er.getMessage());
    }
    catch(CoeficienteAcero er)
    {
      System.out.println(er.getMessage());
    }
  }
}
Se puede observar que en el constructor de la clase NoRaizRealException se hace una llamada al constructor de la clase base, Exception, para pasar la cadena; también se redefinió el método getMessage(), de tal forma que devuelve la cadena con que se inicializa al objeto excepción concatenada con los coeficientes de la ecuación de segundo grado.

No hay comentarios:

Publicar un comentario