Herramientas de usuario

Herramientas del sitio


bloque3:excepciones

Excepciones

Cuando ocurre un error dentro de un método, Java crea un objeto y se lo entrega al entorno de ejecución. El objeto creado es un objeto de la clase Exception o alguna subclase, y contiene información sobre el error: causa, tipo, y estado del programa en el momento que ocurrió el error.

Cuando se crea un objeto de tipo Exception el sistema de ejecución busca un manejador de excepciones. Si no lo encuentra en el método donde ocurre el error, buscará en el método que llamó a ese método, y así sucesivamente hasta llegar al método main. Si en el método main no se ha controlado la excepción, la máquina virtual de Java parará la ejecución del programa.

Tipos de excepciones

En Java existen 2 tipos de excepciones:

  • checked : casi todas las excepciones que heredan de Exception. Obligatorio controlarlas.
  • unchecked : las excepciones de tipo Error, Runtime Excepcion y sus subclases. No es obligatorio controlarlas.

Jerarquía de clases de excepciones de Java

Excepciones unchecked

Las excepciones unchecked (no controladas) se deben a problemas ajenos a los métodos y clases de Java, normalmente errores del código creado por el programador. El compilador no nos obliga a controlarlas.

Ejemplos de estas excepciones son StringIndexOutOfBoundsException, ArrayIndexOutOfBoundsException, NumberFormatException, NullPointerException, etc. Las producen métodos de la clase String como charAt() o substring() cuando nos salimos de rango. También el método parseInt() de la clase Integer, cuando no le pasamos un String parseable.

El compilador nos deja usarlas sin control de errores, y será el programador el encargado de gestionar su uso.

Excepciones checked

Las excepciones checked (controladas) son tipos de errores de los que un programa debería poderse recuperar. Ocurren sobre todo a la hora de trabajar con ficheros. El compilador de Java nos obliga a controlarlas.

Esto quiero decir que si un método produce algúna excepción de este tipo, la llamada a ese método dará un error de compilación (estará subrayada en rojo) hasta que usemos algún mecanismo de control de excepciones.

Existen dos formas de controlar las excepciones checked dentro de un método:

  • Con la sentencia try-catch.
  • Propagándolas: o sea, desentendiéndose del problema en el método actual para que lo resuelva el siguiente método.

Sentencia try-catch

La sentencia try-catch() recuerda a una sentencia de control de flujo (if-else), y de algún modo actúa como tal:

try{
   //Código que puede lanzar una excepción
}catch(Tipo_excepcion e){
   //Código que se ejecuta en caso de excepción
}

Ejemplo de uso:

public static void main(String[] args) {
   String cadena1 = "12";
   String cadena2 = "0";
   String respuesta = "";
   int numerador;
   int denominador;
   int cociente;
 
   try{
      numerador = Integer.parseInt(cadena1);
      denominador = Integer.parseInt(cadena2);
      cociente = numerador / denominador;
      respuesta = String.valueOf(cociente);
   }catch(NumberFormatException e1){
      System.err.println("Las cadenas no se pueden convertir a tipo int");
   }catch(ArithmeticException e2){
      System.err.println("División entre cero");
   }
 
   System.out.println(respuesta);
}

Bloque try

Aquí situamos el código propenso a lanzar excepciónes. La excepción no tiene por qué producirse, pero en caso que se produzca, el bloque try la controlará.

Bloque catch

En este bloque incluiremos los tipos de excepciones que queremos controlar, junto con el código que se ejecutará en caso de ocurrir.

En el momento en que una excepción se produzca en el bloque try, se parará la ejecución del código de ese bloque y se ira al bloque catch que captura dicha excepción, ejecutándo el código de este bloque.

Si se pueden producir excepciones de distintos tipos es posible que haya distintos bloques catch, uno por cada tipo que se quiera capturar. Estos deben ir del tipo más concreto de excepción al tipo más general, ya que cuando se produce una excepción, los bloques catch se evalúan en ese orden.

Bloque finally

El bloque finally, es opcional, y se ejecuta siempre, se produzca una excepción o no.

Se suele usar para cerrar recursos abiertos en caso de producirse una excepción, como por ejemplo cerrar fichero abiertos, cerrar la conexión con la base de datos, etc.

Propagar excepciones: throws

Si no queremos que un método controle una excepción con try-catch podemos propagarla. Esto significa que el método en el que se produce el error se deshace de la excepción y se la pasa al método que le llamó a él. Así el método actual se desentiende de ella, y será ese otro método el encargado de controlarla.

Este proceso se puede repetir hasta llegar al método principal de un programa (main()), que es el último punto donde debemos controlar una excepción. No debemos dejar que las excepciones salgan del método main.

Funcionamiento

Para propagar una excepción se usa la palabra clave throws seguida del tipo de excepción checked que lanza mi programa. Puedo indicar más de una excepción, separadas por comas:

public void escribirCadenaFichero(String cadena) throws IOException{
   PrintWriter escritor = new PrintWriter("ficheto.txt");
   escritor.println(cadena);
   escritor.close();
}
 
/*
El constructor PrintWriter() puede lanzar una excepción ''checked'', 
por lo que estamos obligados a controlarla. 
En lugar de capturarla con un bloque //try-catch//, la propagamos.
*/

Propagar excepciones se suele hacer cuando queremos centralizar el control de una serie de excepciones en un solo bloque de código manejador de excepciones. Puede que un método lance excepciones de un tipo y otro método de otro tipo, pero quiero controlarlas todas desde un lugar concreto del código del programa.

Lanzar excepciones: throw

De la misma forma que los métodos de la API de Java lanzan excepciones, también nuestros métodos pueden lanzarlas.

Por ejemplo, si tenemos métodos que comprueban cosas, pueden lanzar excepciones en caso de error en los datos.

Para lanzar un objeto de tipo Excepción, debemos crearlo y luego lanzarlo con el comando throw:

public void comprobarDiaMes(int dia) throws Exception{
   if(dia > 31 || dia < 1){
      Exception excepcion = new Exception("Numero de dia fuera de rango");
      throw excepcion;
   }

Hay que recordar que si un método lanza una excepción checked, a la hora de usar ese método, el compilador me pedirá controlarla.

También podemos crear nuestras propias Excepciones: debemos crear una clase que herede de la clase del tipo de Excepción que queramos.



© 2020 Fernando Valdeón

bloque3/excepciones.txt · Última modificación: 29/11/2019 00:26 por Fernando Valdeón