Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I Manejo de Excepciones Una excepción en java es un evento que ocurre durante la ejecución de un programa que interrumpe el flujo normal de las instrucciones. Una excepción puede ser causada por fallas de hardware o por errores sencillos de programación como tratar de acceder a un elemento inexistente de un arreglo. Cuando dentro de un método de Java ocurre un error, como los que se describieron anteriormente, el método crea un objeto tipo excepción y se lo entrega al sistema de ejecución. Este objeto de excepción contiene información sobre la excepción como lo es su tipo y el estado del programa cuando ocurrió el error. En Java se dice que ésto es lanzar una excepción. Una vez que un método lanzó una excepción, el sistema de ejecución se encarga de encontrar un método manejador de excepciones para atender la excepción. El conjunto de métodos que posiblemente podrán atender a la excepción son aquellos que estan en la pila de llamadas a métodos en el momento en que se presentó la excepción. El sistema de ejecución realiza su busqueda desde el método mas reciente hasta llegar al mas antiguo. El manejador de excepciones buscado es aquel que sea del mismo tipo que la excepción. Cuando se selecciona un manejador se dice que se ha atrapado la excepción. Si se recorren todos los métodos en la pila y no se encuentra un manejador apropiado, entonces el programa terminará. Ventajas de Utilizar Excepciones Separar el Código de Manejador de Errores La forma tradicional de atender condiciones de error mezcla el código del programa con el código utilizado para manejar errores. Esto provoca que se dificulte la lectura del código principal. El sistema de excepciones de Java permiten separar claramente los dos tipos de código incrementando la legibilidad del programa. El Listado 1 contiene pseudocódigo que ejemplifica el uso de excepciones para atrapar errores que pueden presentarse al leer un archivo. 1 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I leerArchivo { try { abrir el archivo calcular tamaño asignar memoria leer el archivo cerrar el archivo } catch (noAbrioArchivo) { hacer algo } catch (noCalculoTamaño) { hacer algo } catch (noAsignoMemoria) { hacer algo } catch (noLeyo) { hacer algo } catch (noCerroArchivo) { hacer algo } } Listado 1 Ejemplo de Manejo de Errores con Excepciones Propagación de Errores en la Pila de Llamadas a Métodos Otra ventaja del sistema de excepciones es la capacidad para propagar el reporte de un error por la pila de llamadas a métodos. De esta manera, si a un método no le interesa atender un error, permite que el error le llegue al método que si lo atenderá. El Listado 2 ejemplifica la forma de estructurar métodos para que permita la propagación de errores. 2 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I método1 { try { llamar al método2 } catch (excepción) { procesar error } } método2 throws excepción { llamar al método3 } método3 throws excepción { hacer algo que provoque error } Listado 2 Propagación de Errores Agrupación de Tipos de Errores y Distincción entre Errores Las excepciones en Java deben ser tipo Throwable o derivadas de esta clase. Es posible atrapar excepciones especificas, esto es especificando el nombre de la excepción o de manera mas general atrapando la clase de la que se deriva la excepción. La Figura 1 muestra un ejemplo de una jerarquía de clases de excepciones. En ésta se muestra que la clase ArrayException se deriva de Exception y que contiene excepciones para atender los casos en los que se utilice un número de elemento no valido o que no se encuentre el elemento o que el tipo del elemento no sea el apropiado. El Listado 3 muestra tres ejemplos de como pueden atenderse excepciones ya se especificando directamente el nombre de la excepción o de manera mas general especificando una excepción de mayor jerarquía o finalmente especificando una excepción genérica. Este último método no es recomendable para todas las excepciones debido a que atraparía 3 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I demasiadas excepciones lo cual podría provocar mas errores. En los tres casos, el parámetro e se puede utilizar para saber exactamente que tipo de excepción occurrió. Figura 1 Jerarquía de Clases de Excepción catch (InvalidIndexException e) { . . . } catch (ArrayException e) { . . . } catch (Exception e) { . . . } Listado 3 Ejemplos de Manejo de Excepciones Ejemplo de Manejo de Excepciones El Listado 4 es un archivo de programa que no compila debido a que emplea dos métodos que pueden generar excepciones pero no tiene una forma de atenderlas. El Listado 5 list muestra una forma de corregir el programa para que si sea posible compilarlo. 4 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I // Note: This class won't compile by design! // See InputFileDeclared.java for a version of this // class that will compile. import java.io.*; public class InputFile { private FileReader in; public InputFile(String filename) { in = new FileReader(filename); } public String getWord() { int c; StringBuffer buf = new StringBuffer(); do { c = in.read(); if (Character.isWhitespace((char)c)) return buf.toString(); else buf.append((char)c); } while (c != -1); return buf.toString(); } } Listado 4 InputFile.java No atiende excepciones. 5 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I Excepciones Verificadas Java tiene distintos tipos de excepciones. Entre ellas están excepciones de E/S, import java.io.*; public class InputFileDeclared { private FileReader in; public InputFileDeclared(String filename) throws FileNotFoundException { in = new FileReader(filename); } public String getWord() throws IOException { int c; StringBuffer buf = new StringBuffer(); do { c = in.read(); if (Character.isWhitespace((char)c)) return buf.toString(); else buf.append((char)c); } while (c != -1); return buf.toString(); } } Listado 5 Manejo de excepciones correctas. 6 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I excepciones de tiempo de ejecución y excepciones creadas por el usuario. Las excepciones de tiempo de ejecución pueden ocurrir en cualquier momento y pueden ser bastantes. Por esta razón, el compilador no tiene como requisito que se atrapen o especifiquen las excepciones de tiempo de ejecución. Sin embargo, existe otro tipo de excepciones que son las que si son verificadas por el compilador. Estas deben ser atrapadas o especificadas para que pueda compilar. Atrapar o Especificar Java indica que un método debe de atrapar o especificar todas las excepciones verificadas que pueden lanzarse dentro de un método. Atrapar una excepción significa que se proveerá un manejador de excepciones para este tipo de excepción. Especificar una excepción significa que un método no va a atender una excepción por lo que deberá volverla a lanzar para que la atrape un método que si la atenderá. Ésto pasa a formar parte de la interfaz publica del método debido a que los métodos que lo llamen deben saber el tipo de excepción que se lanza para poder tomar decisiones sobre lo que deberá hacer. Como Atrapar y Manejar Excepciones El bloque try Dentro de un bloque try se deben colocar las instrucciones que pueden lanzar una excepción. Todo bloque try deberá tener al menos un bloque catch o un bloque finally. El bloque catch El bloque catch se especifica inmediatamente después de un bloque try. El parámetro de un catch debe contener el tipo de la excepción que se atrapa y el nombre de la variable que representará a la excepción dentro del bloque catch. Por medio de esta variable se podrán acceder a los métodos de la excepción para obtener mayor información sobre ella. Un ejemplo es el método 7 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I getMessage(). Se puede utilizar mas de un bloque catch y de esta manera atrapar distintas excepciones que puedan presentarse. El bloque finally El último paso en la atención a excepciones es el de proporcionar una forma para liberar recursos o cerrar archivos sin importar la excepción que se presentó. El sistema de ejecución siempre ejecuta el bloque finally sin importar lo que sucedió en el bloque try. Ejemplo con Errores // Note: This class won't compile by design! // See ListOfNumbersDeclared.java or ListOfNumbers.java // for a version of this class that will compile. import java.io.*; import java.util.Vector; public class ListOfNumbers { private Vector victor; private static final int size = 10; public ListOfNumbers () { victor = new Vector(size); for (int i = 0; i < size; i++) victor.addElement(new Integer(i)); } public void writeList() { PrintWriter out = new PrintWriter(new FileWriter ("OutFile.txt")); for (int i = 0; i < size; i++) out.println("Value at: " + i + " = " + victor.elementAt(i)); out.close(); } } 8 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I Ejemplo Completo import java.io.*; import java.util.Vector; public class ListOfNumbers { private Vector victor; private static final int size = 10; public ListOfNumbers () { victor = new Vector(size); for (int i = 0; i < size; i++) victor.addElement(new Integer(i)); } public void writeList() { PrintWriter out = null; try { System.out.println("Entering try statement"); out = new PrintWriter(new FileWriter("OutFile.txt")); for (int i = 0; i < size; i++) out.println("Value at: " + i + " = " + victor.elementAt (i)); } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught ArrayIndexOutOfBoundsException: " + e.getMessage()); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); } finally { if (out != null) { System.out.println("Closing PrintWriter"); out.close(); } else { System.out.println("PrintWriter not open"); } } } } 9 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas Universidad Autónoma de Baja California Facultad de Ingeniería Apuntes de Programación Orientada a Objetos I Ejemplo 2 import java.io.*; import java.util.Vector; public class ListOfNumbersDeclared { private Vector victor; private static final int size = 10; public ListOfNumbersDeclared () { victor = new Vector(size); for (int i = 0; i < size; i++) victor.addElement(new Integer(i)); } public void writeList() throws IOException, ArrayIndexOutOfBoundsException { PrintWriter out = new PrintWriter(new FileWriter ("OutFile.txt")); for (int i = 0; i < size; i++) out.println("Value at: " + i + " = " + victor.elementAt(i)); out.close(); } } 10 de 10 Elaborado por: M.C. Cecilia M. Curlango Rosas