====== 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 ==== {{ :bloque3:jerarquiaexcepciones.png?600 |}} ==== 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. ---- {{ vimeo>313833143?medium }} ---- (c) {{date> %Y}} Fernando Valdeón