29
Manejo de Excepciones H. Tejeda Abril 2016 ´ Indice 1. Introducci´ on 1 2. Intentar c´ odigo y capturar excepciones 5 3. Lanzar y atrapar excepciones m´ ultiples 11 4. Bloque finally 14 5. Ventajas del manejo de excepci´ on 16 6. Especificar excepciones que un m´ etodo puede lanzar 18 7. Traza de excepciones en la pila de llamadas 21 8. Creaci´ on de clases Exception propias 23 9. Uso de afirmaciones 26 1. Introducci´ on Una excepci´ on es una condici´ on inesperada o error. Los programas que se escriben pueden generar varios tipos de excepciones potenciales: Podr´ ıa emitir un comando para leer un archivo de un disco, pero el archivo no existe. Podr´ ıa intentar escribir datos a un disco, pero el disco est´ a lleno o no formateado. Podr´ ıa pedir entrada al usuario, pero el usuario ingresa un tipo de dato no v´ alido. 1

Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Embed Size (px)

Citation preview

Page 1: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Manejo de Excepciones

H. Tejeda

Abril 2016

Indice

1. Introduccion 1

2. Intentar codigo y capturar excepciones 5

3. Lanzar y atrapar excepciones multiples 11

4. Bloque finally 14

5. Ventajas del manejo de excepcion 16

6. Especificar excepciones que un metodo puede lanzar 18

7. Traza de excepciones en la pila de llamadas 21

8. Creacion de clases Exception propias 23

9. Uso de afirmaciones 26

1. Introduccion

Una excepcion es una condicion inesperada o error. Los programas que se escriben pueden generarvarios tipos de excepciones potenciales:

Podrıa emitir un comando para leer un archivo de un disco, pero el archivo no existe.

Podrıa intentar escribir datos a un disco, pero el disco esta lleno o no formateado.

Podrıa pedir entrada al usuario, pero el usuario ingresa un tipo de dato no valido.

1

Page 2: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Podrıa intentar acceder un arreglo con un subındice que no es valido.

Estos errores son llamados excepciones porque no son ocurrencias usuales. El manejo de excep-ciones es el nombre para las tecnicas orientadas al objeto que manejan tales errores. Excepcionesno planeadas que ocurren durante la ejecucion del programa son tambien llamadas excepcionesen tiempo de ejecucion, en contraste con errores de sintaxis que son descubiertos durante lacompilacion del programa.

Java incluye dos clases basicas de errores: Error y Exception. Ambas clases descienden de la claseThrowable, como se muestra enseguida. Como todas las otras clases en Java, Error y Exception

originalmente descienden de Object.

java.lang.Object

|

+--java.lang.Throwable

|

+--java.lang.Exception

| |

| +--java.io.IOException

| |

| +--java.lang.RuntimeException

| | |

| | +--java.lang.ArithmeticException

| | |

| | +--java.lang.IndexOutOfBoundsException

| | | |

| | | +--java.lang.ArrayIndexOutOfBoundsException

| | |

| | +--java.util.NoSuchElementException

| | | |

| | | +--java.util.InputMismatchException

| | |

| | +--Otras...

| |

| +--Otras...

|

+--java.lang.Error

|

+--java.lang.VirtualMachineError

| |

| +--java.lang.OutOfMemoryError

| |

| +--java.lang.InternalError

| |

| +--Otras...

|

+--Otras...

2

Page 3: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

La clase Error representa los errores mas serios de los cuales el programa usualmente no se puedenrecuperar. Podrıa haber memoria insuficiente para ejecutar un programa. Usualmente, no se usan oimplementan objetos Error en el programa. Un programa no se puede recuperar de las condicionesError por su propia cuenta.

La clase Exception comprende errores menos serios que representan condiciones no usuales quesurgen mientras un programa se ejecuta y del cual el programa se puede recuperar. Estos errores sedan al usar un subındice de arreglo no valido o realizando ciertas operaciones aritmeticas ilegales.

Java muestra un mensaje Exception cuando el codigo del programa podrıa haber prevenido unerror. La aplicacion Division, codigo 1, contiene en el metodo main() tres declaraciones de enteros,peticiones al usuario de valores para dos variables, y el calculo del valor del tercer entero haciendola division de los valores dados.

1 import java . u t i l . Scanner ;2 public class Div i s i on {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int numerador , denominador , r e s u l t a d o ;6 System . out . p r i n t ( ” I n g r e s a r e l numerador >> ” ) ;7 numerador = entrada . next Int ( ) ;8 System . out . p r i n t ( ” I n g r e s a r e l denominador >> ” ) ;9 denominador = entrada . next Int ( ) ;

10 r e s u l t a d o = numerador / denominador ;11 System . out . p r i n t l n ( numerador + ” / ” + denominador +12 ” = ” + r e s u l t a d o ) ;13 }14 }

Codigo 1: La clase Division.

Como se muestra en la siguiente salida, al ejecutar la aplicacion Division y habiendo el usuarioingresado un cero para el denominador, se genera un mensaje de excepcion. Java no permite divisionentera por cero, pero la division flotante por cero es permitida, dando el resultado Infinity.Los programadores dicen que el programa experimento un choque, para indicar que el programatermino prematuramente con un error. El termino “choque” quizas evoluciono del error de hardwareque ocurre cuando una cabeza de lectura/escritura abruptamente hace contacto con un disco duro,para incluir los errores de software que causan la falla del programa.

$ java Division

Ingresar el numerador >> 3

Ingresar el denominador >> 0

Exception in thread "main" java.lang.ArithmeticException: / by zero

at Division.main(Division.java:10)

De la salida de la aplicacion, mostrada previamente, la Exception es una java.lang.Arithmetic-

Exception la cual es una de muchas subclases de Exception. Java conoce mas de 75 categorıas deException con nombres raros como ActivationException, AlreadyBoundException, AWTExcep-tion, CloneNotSupportedException, PropertyVetoException, y UnsupportedFlavorException.

3

Page 4: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Ademas del tipo de Exception que se muestra en la ejecucion se muestra alguna informacion delerror (“/ by zero”), el metodo que genero el error(Division.main), y el archivo y numero de lıneapara el error(Division.java, lınea 10).

En la siguiente salida se muestran dos ejecuciones mas de la aplicacion Division. En cada ejecucion,el usuario ha metido datos no enteros para el denominador, primero una cadena de carateres, yluego un valor de punto flotante. De los mensajes de error se ve que en ambos casos la Exception

es una InputMismatchException. La ultima lınea del mensaje indica que el problema ocurrio en lalınea 9 de la aplicacion, y el mensaje de error que le antecede muestra que el problema ocurrio dentrode la llamada a nextInt(). Como el usuario no ingreso un entero, el metodo nextInt() fallo. Porsupuesto que no se quiere modificar el metodo nextInt() que reside en la clase Scanner, se prefierevolver a ejecutar el programa y meter un entero, o modificar el programa para que estos errores nopuedan ocurrir.

$ java Division

Ingresar el numerador >> 12

Ingresar el denominador >> tres

Exception in thread "main" java.util.InputMismatchException

at java.util.Scanner.throwFor(Scanner.java:909)

at java.util.Scanner.next(Scanner.java:1530)

at java.util.Scanner.nextInt(Scanner.java:2160)

at java.util.Scanner.nextInt(Scanner.java:2119)

at Division.main(Division.java:9)

$ java Division

Ingresar el numerador >> 12

Ingresar el denominador >> 3.0

Exception in thread "main" java.util.InputMismatchException

at java.util.Scanner.throwFor(Scanner.java:909)

at java.util.Scanner.next(Scanner.java:1530)

at java.util.Scanner.nextInt(Scanner.java:2160)

at java.util.Scanner.nextInt(Scanner.java:2119)

at Division.main(Division.java:9)

La lista de mensajes de error que se muestran en los intentos de ejecucion mostrados previamentees llamada una lista del historial de seguimiento de la pila, o un seguimiento de la pila.La lista muestra cada metodo que fue llamado conforme el programa se ejecutaba.

Solo porque una excepcion ocurra, no es obligatorio manejarla. Se puede dejar el codigo sin mo-dificacion pero, la terminacion del programa es abrupta. Posiblemente algun usuario podrıa estarmolesto si el programa termina abruptamente. Sin embargo, si el programa es usado para tareasde mision crıtica tales como el control del trafico aereo, o para monitorear los signos vitales de unpaciente en una cirugıa, una conclusion abrupta podrıa ser desastrosa. Las tecnicas de manejo deerror orientadas al objeto dan soluciones elegantes y seguras para errores.

Se pueden escribir programas sin usar tecnicas de manejo de excepciones. Posiblemente la solucionde manejo de errores mas comun ha sido el uso de una decision para evitar un error. Por ejemplo,se puede cambiar el metodo main() de la clase Division para evitar dividir por cero agregando la

4

Page 5: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

decision como se muestra en la aplicacion DivisionIf, codigo 2.

1 import java . u t i l . Scanner ;2 public class D i v i s i o n I f {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int numerador , denominador , r e s u l t a d o ;6 System . out . p r i n t ( ” I n g r e s a r e l numerador >> ” ) ;7 numerador = entrada . next Int ( ) ;8 System . out . p r i n t ( ” I n g r e s a r e l denominador >> ” ) ;9 denominador = entrada . next Int ( ) ;

10 i f ( denominador == 0)11 System . out . p r i n t l n ( ”No se puede d i v i d i r por 0” ) ;12 else {13 r e s u l t a d o = numerador / denominador ;14 System . out . p r i n t l n ( numerador + ” / ” + denominador +15 ” = ” + r e s u l t a d o ) ;16 }17 }18 }

Codigo 2: Aplicacion DivisionIf.

La aplicacion DivisionIf muestra un mensaje al usuario cuando cero es ingresado para el valordel denominador, pero no se puede recuperar cuando un dato no entero, como una cadena o unvalor punto flotante, es ingresado.

Los programas que pueden manejar excepciones apropiadamente se dice que son mas tolerantes a lasfallas y robustos. Las aplicaciones tolerantes a las fallas son disenadas para que puedan continuaroperando, posiblemente a un nivel reducido, cuando alguna parte del sistema falla. La robustezrepresenta el grado en el cual un sistema es resistente al uso, manteniendo el funcionamientocorrecto.

Es importante entender las tecnicas de manejo de excepciones porque los metodod incorporados enJava lanzaran excepciones a los programas.

2. Intentar codigo y capturar excepciones

En la terminologıa orientada al objeto, se “intenta (try)” un procedimiento que podrıa causar unerror. Un metodo que detecta una condicion de error “lanza (throws) una excepcion”, y el codigode bloque que procesa el error “atrapa (catch) la excepcion”.

Cuando se crea un segmento de codigo en el cual algo podrıa ir mal, se coloca el codigo en unbloque try, el cual es un bloque de codigo que se intenta ejecutar mientras se reconoce que unaexcepcion podrıa ocurrir. Un bloque try consiste de los siguientes elementos:

La palabra reservada try.

Una llave de apertura.

Sentencia ejecutables, incluyendo algunas que podrıan causar excepciones.

5

Page 6: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Una llave de cierre.

Para manejar una excepcion lanzada, se pueden codificar uno o mas bloques catch siguiendoinmediatamente al bloque try. Un bloque catch es un segmento de codigo que puede manejaruna excepcion que podrıa ser lanzada por el bloque try que le precede. La excepcion podrıa seruna que es lanzada automaticamente, o se podrıa explıcitamente escribir una sentencia throw. Unasentencia throw es una que manda un objeto Exception fuera de un bloque o un metodo paraque pueda ser manejada donde sea. Una Exception lanzada puede ser capturada por un bloquecatch. Cada bloque catch puede “atrapar” un tipo de excepcion, es decir, un objeto que es deltipo Exception o de sus clases hijas. Se crea un bloque catch poniendo los siguientes elementos:

La palabra reservada catch.

Un parentesis de apertura.

Un tipo o subtipo Exception.

Un identificador para una instancia del tipo Exception.

Un parentesis de cierre.

Una llave de apertura.

Las sentencias que toman la accion que se quiere usar para manejar la condicion de error.

Una llave de cierre.

Se muestra enseguida el formato general de un metodo que incluye un par try...catch. Un bloquecatch se parece a un metodo llamado catch() que toma un argumento que es algun tipo deException. Sin embargo, no es un metodo; no tiene tipo que se devuelve, y no se puede llamardirectamente. Algunos programadores se refieren a un bloque catch como una “clausula catch”.

tipoDevuelto nombreMetodo(parametros opcionales) {// sentencias opcionales previas al codigo que se intentara

try {// sentencias que podrıan generar una excepcion

}catch (Exception algunaExcepcion) {

// acciones que se haran si la excepcion ocurre

}// sentencias opcionales que ocurren despues del try,

// ya sea que el bloque catch se ejecute o no

}

Cuadro 1: Formato try...catch en un metodo.

En el formato, algunaExcepcion representa un objeto de la clase Exception o alguna de sussubclases. Si una excepcion ocurre durante la ejecucion del bloque try, las sentencias en el bloque

6

Page 7: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

catch se ejecutan. Si no ocurre una excepcion dentro del bloque try, el bloque catch no se ejecuta.De cualquier forma, las sentencias que siguen el bloque catch se ejecutan normalmente.

La aplicacion DivisionPorCeroAtrapada, codigo 3, mejora la clase Division. El metodo main()

contiene un bloque try con codigo que intenta dividir. Cuando una division entera ilegal es inten-tada, una ArithmeticException es automaticamente creada y el bloque catch es ejecutado.

1 import java . u t i l . Scanner ;2 public class Divis ionPorCeroAtrapada {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int numerador , denominador , r e s u l t a d o ;6 System . out . p r i n t ( ” I n g r e s a r e l numerador >> ” ) ;7 numerador = entrada . next Int ( ) ;8 System . out . p r i n t ( ” I n g r e s a r e l denominador >> ” ) ;9 denominador = entrada . next Int ( ) ;

10 try {11 r e s u l t a d o = numerador / denominador ;12 System . out . p r i n t l n ( numerador + ” / ” + denominador +13 ” = ” + r e s u l t a d o ) ;14 }15 catch ( Arithmet icExcept ion e r r o r ) {16 System . out . p r i n t l n ( ” Intento de d i v i d i r por 0” ) ;17 }18 }19 }

Codigo 3: Aplicacion DivisionPorCeroAtrapada.

Enseguida se muestra la salida de dos ejecuciones de la aplicacion, una con una excepcion generaday una sin excepcion.

$ java DivisionPorCeroAtrapada

Ingresar el numerador >> 20

Ingresar el denominador >> 5

20 / 5 = 4

$ java DivisionPorCeroAtrapada

Ingresar el numerador >> 20

Ingresar el denominador >> 0

Intento de dividir por 0

Nota. En la aplicacion DivisionPorCeroCapturada, las operaciones lanzar y atrapar estan en el

mismo metodo. Despues se revisara que los lanzamientos y su correspondiente bloque de captura

frecuentemente estan en metodos separados.

Nota. Si se quiere mandar mensajes de error a una localidad diferente a la salida “normal”, se puede

usar System.err en vez de System.out. Por ejemplo, si una aplicacion escribe un reporte a un

archivo de disco especıfico, se podrıa querer que los errores se escriben en una localidad diferente,

como en otro disco o a la pantalla.

7

Page 8: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Cualquier ArithmeticException generada dentro del bloque try podrıa ser atrapada por el bloquecatch en el metodo, para la aplicacion DivisionPorCeroAtrapada. Se puede usar el metodo deinstancia getMessage() calificado con la excepcion atrapada, que ArithmeticException heredade la clase Throwable, en vez de poner su propio mensaje.

En la aplicacion DivisionPorCeroAtrapada2, codigo 4, usa el metodo getMessage(), lınea 16,para generar el mensaje que “viene con” el argumento atrapado ArithmeticException para elbloque catch. Al ejecutar esta aplicacion con un denominador que sea cero, se muestra el mensaje“/ by zero”.

1 import java . u t i l . Scanner ;2 public class Divis ionPorCeroAtrapada {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int numerador , denominador , r e s u l t a d o ;6 System . out . p r i n t ( ” I n g r e s a r e l numerador >> ” ) ;7 numerador = entrada . next Int ( ) ;8 System . out . p r i n t ( ” I n g r e s a r e l denominador >> ” ) ;9 denominador = entrada . next Int ( ) ;

10 try {11 r e s u l t a d o = numerador / denominador ;12 System . out . p r i n t l n ( numerador + ” / ” + denominador +13 ” = ” + r e s u l t a d o ) ;14 }15 catch ( Arithmet icExcept ion e r r o r ) {16 System . out . p r i n t l n ( ” Intento de d i v i d i r por 0” ) ;17 }18 }19 }

Codigo 4: Aplicacion DivisionPorCeroAtrapada2.

El mensaje “/ by zero” ya habıa sido visto previamente, y fue cuando el programa, Division, notenıa manejo de excepciones.

Por supuesto que se quiere hacer mas que mostrar un mensaje de error en el bloque catch; despuesde todo, Java lo hacıa sin requerir escribir codigo para atrapar cualquier excepcion. Se podrıa quereragregar codigo para corregir el error; tal codigo podrıa forzar la aritmetica al dividir por uno envez de cero. Enseguida se muestra un codigo try...catch que realiza lo comentado. Despues delbloque catch, la aplicacion podrıa continuar con la garantıa que resultado tiene un valor valido,aun si la division funciono en el bloque try y el bloque catch no se ejecuto, o el bloque catch

arregla el error.

try {resultado = numerador / denominador;

}catch (ArithmeticException error) {

resultado = numerador / 1;

}// el programa continua aquı; resultado esta garantizado

// para tener un valor valido

8

Page 9: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Uso de un bloque try para hacer programa infalibles

Uno de los usos mas comunes del bloque try es para esquivar errores de entrada de datos delusuario. Como cuando el usuario en la aplicacion Division ingresa un caracter o un numero depunto flotante en respuesta a la llamada del metodo nextInt() y hace que la aplicacion choque.Usando un bloque try se puede permitir manejar excepciones potenciales de conversion de datoscausadas por usuarios distraidos. Las llamadas a nextInt() o nextDouble() se ponen en el bloquetry y luego se maneja cualquier error generado.

Despues de cualquier llamada al metodo next(), nextInt(), o nextDouble() se agrega una lla-mada a nextLine() para leer la tecla Intro remanente en el bufer de entrada, antes de llamadassubsecuentes nextLine(). Cuando se intenta convertir a dato numerico en un bloque try y esseguido por otro intento de conversion, se debe tener en cuenta los caracteres remanentes dejadosen el bufer de entrada. En la aplicacion IngresoEnteros, codigo 5, se aceptan y se muestran unarreglo de seis enteros.

1 import java . u t i l . Scanner ;2 public class Ingre soEnteros {3 public stat ic void main ( St r ing [ ] a rgs ) {4 int [ ] l i s taNumeros = {0 , 0 , 0 , 0 , 0 , 0} ;5 Scanner entrada = new Scanner ( System . in ) ;6 for ( int x = 0 ; x < l i s taNumeros . l ength ; ++x ) {7 try{8 System . out . p r i n t ( ” Ingre sa un entero >> ” ) ;9 l i s taNumeros [ x ] = entrada . next Int ( ) ;

10 }11 catch ( Exception e ) {12 System . out . p r i n t l n ( ” Ocurr i o una excepc i on” ) ;13 }14 // entrada . nextLine ( ) ;15 }16 System . out . p r i n t ( ”Los numeros son : ” ) ;17 for ( int num: l i s taNumeros )18 System . out . p r i n t (num + ” ” ) ;19 System . out . p r i n t l n ( ) ;20 }21 }

Codigo 5: Aplicacion IngresoEnteros.

Al ejecutar la aplicacion IngresoEnteros y poner un dato valido para el primer numero, se obtienela siguiente salida, la cual sı muestra “Ocurrio una excepcion”, pero al usuario no se le permiteingresar datos para cualquiera de los numeros restantes. El problema se puede corregir descomen-tando la llamada a nextLine(), lınea 14, del codigo anterior. De esta forma el mensaje de excepciones puesto, y se permite al usuario continuar ingresando datos.

$ java IngresoEnteros

Ingresa un entero >> a

Ocurrio una excepcion

Ingresa un entero >> Ocurrio una excepcion

Ingresa un entero >> Ocurrio una excepcion

9

Page 10: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Ingresa un entero >> Ocurrio una excepcion

Ingresa un entero >> Ocurrio una excepcion

Ingresa un entero >> Ocurrio una excepcion

Los numeros son: 0 0 0 0 0 0

Actividad 1. Descomentar la lınea 14 de la aplicacion IngresoEnteros, compilar y ejecutar laapliacion meter un dato no valido para observar que indica el error

Declaracion e inicializacion de variables en bloques try...catch

Se puede incluir cualquier sentencia legal dentro de un bloque try o catch, incluyendo la declaracionde variables. Una variable declarada dentro de un bloque es local a ese bloque, por lo que estavariable sirve solo para un proposito temporal.

Si se quiere usar una variable tanto en un bloque try, como en un catch y despues, entonces sedebe declarar la variable antes de que el bloque try inicie. Si el valor inicial a esta variable seasignara dentro del bloque try...catch, se debe tener cuidado que la variable reciba un valorutil; de otra forma, cuando se use la variable despues del bloque try...catch, el programa nocompilara.

En el programa PruebaVariableNoInicializada, codigo 6, x esta declarada y su valor es asignadopor la entrada del usuario en el bloque try...catch. Como el usuario podrıa no ingresar un entero,la conversion podrıa fallar, y una excepcion podrıa ser lanzada. En este codigo el bloque catch solomuestra un mensaje y no asigna un valor a x. Cuando el programa intenta mostrar x despues delbloque catch, un mensaje de error es generado.

Actividad 2. Compilar el codigo PruebaVariableNoInicializada para ver el mensaje de error.

1 import java . u t i l . Scanner ;2 public class PruebaVar iab l eNoIn i c i a l i zada {3 public stat ic void main ( St r ing [ ] a rgs ) {4 int x ;5 Scanner entrada = new Scanner ( System . in ) ;6 try {7 System . out . p r i n t ( ” Ingre sa un entero )))) ) ” ;8 x = entrada . next Int ( ) ;9 }

10 catch ( Exception e ) {11 System . out . p r i n t l n ( ” Ocurr i o excepc i on” ) ;12 }13 System . out . p r i n t l n ( ”x es ” + x ) ;14 }15 }

Codigo 6: Aplicacion PruebaVariableNoInicializada.

Se tienen tres opciones para arreglar este error:

Se puede asignar un valor a x antes de que el bloque try inicie. De esta forma, aun si unaexcepcion es lanzada, x tendra un valor usable para mostrar en la ultima sentencia.

10

Page 11: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Se puede asignar un valor usable a x dentro del bloque catch. De esta forma, si una excepciones lanzada, x tendra otra vez un valor usable.

Se puede mover la sentencia de salida al bloque try para que en el caso de que el usuarioingrese un entero muestre ese valor, y si la conversion falla entonces se deja el bloque try,para ser ejecutado el bloque catch mostrando el mensaje de error y sin usar x.

Actividad 3. Modificar la aplicacion DivisionPorCeroAtrapada que los enteros sean solicitadoscon cuadros de dialogo de entrada y el metodo Integer.ParseInt() para convertir las cadenasdevueltas por los cuadros de dialogo de entrada en enteros. De igual forma modificar el bloquecatch para mostrar el error con un cuadro de dialogo.

3. Lanzar y atrapar excepciones multiples

Se pueden poner tantas sentencias como se requiera dentro de un bloque try, y se pueden atrapartantas excepciones como se quiera. Si se intenta mas de una sentencia, solo la primera sentenciageneradora de error lanza una excepcion. Tan pronto la excepcion ocurre, la logica se transfiere albloque catch, lo cual deja el resto de las sentencias en el bloque try sin ejecutar.

Cuando un programa contiene varios bloques catch, estos son examinados en secuencia hasta queun apareamiento es encontrado para el tipo de excepcion que ha ocurrido. Entonces, el bloquecatch apareado se ejecuta, y cada bloque catch restante es omitido.

Considerar la aplicacion DivisionPorCeroAtrapada3, codigo 7, donde el metodo main() lanzados tipos de objetos Exception: una ArithmeticException y una InputMismatchException. Elbloque try en la aplicacion rodea todas las sentencias en la cual las excepciones podrıan ocurrir.

11

Page 12: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

1 import java . u t i l . ∗ ;2 public class Divis ionPorCeroAtrapada3 {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int numerador , denominador , r e s u l t a d o ;6 try {7 System . out . p r i n t ( ” I n g r e s a r e l numerador >> ” ) ;8 numerador = entrada . next Int ( ) ;9 System . out . p r i n t ( ” I n g r e s a r e l denominador >> ” ) ;

10 denominador = entrada . next Int ( ) ;11 r e s u l t a d o = numerador / denominador ;12 System . out . p r i n t l n ( numerador + ” / ” + denominador +13 ” = ” + r e s u l t a d o ) ;14 }15 catch ( Exception e ) {16 System . out . p r i n t l n ( e . getMessage ( ) ) ;17 }18 catch ( Arithmet icExcept ion e r r o r ) {19 System . out . p r i n t l n ( e r r o r . getMessage ( ) ) ;20 }21 catch ( InputMismatchException e r r o r ) {22 System . out . p r i n t l n ( ”Tipo de dato i n c o r r e c t o ” ) ;23 }24 }25 }

Codigo 7: Aplicacion DivisionPorCeroAtrapada3.

Nota. La aplicacion DivisionPorCeroAtrapada3 debe importar la clase java.util.InputMis-

matchException para poder usar un objeto InputMismatchException. El paquete java.util es

tambien ocupado por la clase Scanner, ası que es mas facil importar el paquete completo.

Nota. Si se usa el metodo getMessage() con el objeto InputMismatchException, se vera que

el mensaje es null, porque null es el valor del mensaje por defecto para un objeto InputMis-

matchException.

Para la aplicacion DivisionPorCeroAtrapada3 el bloque try se ejecuta y varias salidas son posibles:

Si el usuario ingresa dos enteros usables, resultado es calculado, la salida normal es mostrada,y ningun bloque catch se ejecuta.

Si el usuario ingresa un valor no valido ya sea en la lınea 7, o en la lınea 9, un objetoInputMismatchException es creado y lanzado. Cuando el programa encuentra el primerbloque catch el bloque es pasado porque la excepcion generada InputMismatchException

no empata con ArithmeticException. Al encontrar el programa el segundo bloque catch, eltipo empata, y el mensaje “Tipo de dato incorrecto” es mostrado.

Si el usuario ingresa cero para el denominador, la sentencia de division lanza una Arithmetic-

Exception, y el bloque try es abandonado. Cuando el programa encuentra el primer bloquecatch, el tipo de excepcion empata, el valor del metodo getMessage() es mostrado, y luegoel segundo bloque catch es pasado.

12

Page 13: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Cuando se ponen varios bloques catch siguiendo un bloque try, se debe tener cuidado de que algu-nos bloques catch no se hagan inalcanzables. Por ejemplo, si un primer bloque catch atrapan unaArithmeticException y enseguida otra atrapa una Exception, los errores ArithmeticExceptioncausan que el primer bloque catch se ejecute y otros tipos que deriven de Exception “caigan”al bloque catch Exception mas general. Por otra parte, si se invierte la secuencia de los bloquescatch para que atrape primero el bloque catch Exception, aun las ArithmeticException seranatrapadas por el primer catch, y de esta forma el bloque catch ArithmeticException sera inal-canzable ya que la ArithmeticException sera atrapada por el catch Exception, y por lo tantola clase no compilara. Se deben de poner los bloques catch de forma que los mas especializadosesten primero y al final los mas generales. Es decir, cada excepcion debera caer a traves de tantosbloques catch como sea necesario hasta llegar con el que lo procesara.

Nota. Otras sentencias que son inalcanzables son aquellas que siguen despues de una sentencia

return en un metodo. Crear bloques catch inalcanzables provoca un error del compilador que

genera un mensaje indicando que la excepcion “has already been caught” (ya ha sido atrapada).

En ocasiones se quiere ejecutar el mismo codigo no importando cual tipo de excepcion ocurre. Enla aplicacion DivisionPorCeroAtrapada3, codigo 7, cada uno de los dos bloques catch muestranun mensaje unico, pero se podrıa querer que ambos bloques catch muestren el mismo mensaje.Como ArithmeticException e InputMismatchException son subclases de Exception, se puedereescribir el codigo 7, como se muestra en el codigo 8, usando un bloque catch generico, lıneas15—17, que puede atrapar cualquier tipo de objeto Exception.

1 import java . u t i l . ∗ ;2 public class Divis ionPorCeroAtrapada4 {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int numerador , denominador , r e s u l t a d o ;6 try {7 System . out . p r i n t ( ” I n g r e s a r e l numerador >> ” ) ;8 numerador = entrada . next Int ( ) ;9 System . out . p r i n t ( ” I n g r e s a r e l denominador >> ” ) ;

10 denominador = entrada . next Int ( ) ;11 r e s u l t a d o = numerador / denominador ;12 System . out . p r i n t l n ( numerador + ” / ” + denominador +13 ” = ” + r e s u l t a d o ) ;14 }15 catch ( Exception e r r o r ) {16 System . out . p r i n t l n ( ” Operaci on no e x i t o s a ” ) ;17 }18 }19 }

Codigo 8: Aplicacion DivisionPorCeroAtrapada4.

El bloque catch generico de la clase DivisionPorCeroAtrapada4 acepta un tipo de argumentoException generico lanzado por cualquier sentencia potencialmente causante del error, ası el bloquegenerico actua como un bloque “atrapa todo”. Cuando un error aritmetico o de entrada ocurre, laexcepcion lanzada es “promovida” a un error Exception en el bloque catch.

Actividad 4. Ejecutar la aplicacion DivisionPorCeroAtrapada4 para ver que no importando el

13

Page 14: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

tipo de error que ocurra durante la ejecucion del programa, el mensaje general “Operacion noexitosa” es mostrado

Como una caracterıstica nueva en Java 7, un bloque catch ya puede ser escrito para atraparmultiples tipos de excepciones especıficas. Por ejemplo, el siguiente bloque catch atrapa dos tiposde excepciones. Cuando cualquiera es atrapada, su identificador local es e.

catch (ArithmeticException, InputMismatchException e) {...

}

Un metodo puede lanzar cualquier cantidad de tipos de excepciones, sin embargo varios progra-madores consideran que es un estilo pobre para un metodo lanzar y atrapar mas de tres o cuatrostipos. Si lo hace, una de las siguientes condiciones podrıa ser cierta:

Quizas el metodo esta intentando realizar muchas tareas diversas y entonces deberıa serdividido en metodos mas pequenos.

Quizas los tipos de excepcion lanzados son muy especıficos y deberıan ser generalizados, comose hizo en la aplicacion DivisionPorCeroAtrapada4, codigo 8.

Actividad 5. Usar la actividad 2 para agregar un bloque catch que atrape un objeto NumberFor-

matException. Si este bloque se ejecuta, mostrar un mensaje de error, asignar a numerador ydenominador el valor por defecto 999, y forzar resultado a uno. Ejecutar la aplicacion para confirmarque el programa trabaja apropiadamente si se dan dos enteros usables, un cero no usable para elsegundo entero, o datos no enteros como cadenas conteniendo caracteres alfabeticos o de puntuacion.

4. Bloque finally

Cuando se tienen acciones que se deben hacer al final de una secuencia try...catch, se puedeusar un bloque finally. El codigo dentro de un bloque finally se ejecuta no importando siel bloque try precedente identifica una excepcion. Generalmente, el bloque finally se usa pararealizar tareas de limpieza que deben suceder no importando si alguna excepcion ocurrio o no, ysi cualquier excepcion que ocurrio fue capturada o no. El siguiente formato muestra una secuenciatry....catch que usa un bloque finally.

try {// sentencias a intentar

}catch (Exception e) {

// acciones que ocurren si Exception fue lanzada

}finally {

// acciones que ocurren si el bloque catch fue ejecutado o no

}

14

Page 15: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

En una secuencia try...catch que no incluya un bloque finally, ver el formato del cuadro 1, lassentencias opcionales que ocurren despues del try, al final del metodo, podrıan nunca ser ejecutadaspor al menos dos razones.

Cualquier bloque try podrıa lanzar un objeto Exception para el cual no se proporcione unbloque catch. En el caso de una excepcion no manejada, la ejecucion del programa terminainmediatamente, la excepcion es mandada al sistema operativo para que la maneje, y elmetodo actual es abandonado.

El bloque try o catch podrıan contener la sentencia System.exit();, la cual detiene laejecucion inmediatamente.

Cuando se incluye un bloque finally, se asegura que las sentencias finally se ejecutaran antesque el metodo sea abandonado, aun si el metodo concluye prematuramente. Los programadoresusan un bloque finally cuando el programa usa archivos de datos que deban cerrarse. El formatodel cuadro representa parte de la logica para un programa que maneja archivos.

try {// Abrir el archivo

// Leer el archivo

// Colocar los datos del archivo en un arreglo

// Calcular el promedio de los datos

// Mostrar el promedio

}catch (IOException e) {

// mostrar un mensaje de error

// salir de la aplicacion

}finally {

// Si el archivo esta abierto entonces cerrarlo.

}

Cuadro 2: Pseudocodigo que intenta leer un archivo y manejar una excepcion IOException

El pseudocodigo del cuadro 2 representa una aplicacion que abre un archivo; en Java, si un archivono existe cuando se abre, una excepcion entrada/salida, o IOException, es lanzada y el bloquecatch puede manejar el error. Como el pseudocodigo usa un arreglo, una IndexOutOfBoundsEx-

ception no atrapada podrıa ocurrir aun si se pudo abrir el archivo, esta excepcion ocurre cuandoun subındice no esta en rango de subındices validos. Tambien podrıa dividirse por cero y unaArithmeticException no atrapada podrıa ocurrir. En cualquiera de estos eventos, se podrıa querercerrar el archivo antes de proceder. Usando el bloque finally, se asegura que el archivo sera cerradoporque el codigo en este bloque se ejecuta antes que el control regrese al sistema operativo. El codigoen el bloque finally se ejecuta no importando cual de las siguientes salidas del bloque try ocurra:

El bloque try termina normalmente.

El bloque catch se ejecuta.

15

Page 16: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Una excepcion no capturada causa que el metodo sea abandonado prematuramente. Unaexcepcion no capturada no permite que el bloque try concluya, ni causa que un bloquecatch sea ejecutado.

Si una aplicacion pudiera lanzar varios tipos de excepciones, se puede intentar algun codigo, atraparla posible excepcion, intentar algun codigo mas y atrapar la excepcion, y ası sucesivamente. La mejoralternativa es intentar todas las sentencias que podrıan lanzar excepciones, y luego incluir todoslos bloques catch necesarios y un bloque finally opcional. Esta es la alternativa mostrada en elcuadro 2, y resulta en un logica que es mas facil de entender.

Se puede evitar usar un bloque finally, pero se podrıa necesitar repetir codigo. Para el pseu-docodigo del cuadro 2 para evitar usar el bloque finally se podrıa insertar la sentencia “Si elarchivo esta abierto entonces cerrrarlo” como la ultima sentencia en el bloque try y despues demostrar el mensaje de error en el bloque catch. Sin embargo, escribiendo codigo solo una vez en elbloque finally es mas simple y menos susceptible a error.

Nota. Si un bloque try llama al metodo System.exit() y el bloque finally llama al mismo

metodo, el metodo exit() en el bloque finally se ejecuta. La llamada del metodo exit() del

bloque try es abandonado.

5. Ventajas del manejo de excepcion

Antes de la llegada de los lenguajes orientados al objeto, los errores potenciales del programa fueronmanejados usando algo enredado, metodos propensos a error. Un programa procedural tradicionalno orientado al objeto podrıa realizar tres metodos que dependen de otros usando codigo queproporcione revision similar al pseudocodigo del cuadro 3.

llamar al metodoA()

if metodoA() trabajo {llamar al metodoB()

if metodoB() trabajo {llamar al metodoC()

if metodoC() trabajo

todo esta bien, ası que mostrar resultadoFinal

else

poner codigoError a ’C’

}else

poner codigoError a ’B’

}else

poner codigoError a ’A’

Cuadro 3: Pseudocodigo representando revision tradicional de error

16

Page 17: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

El pseudocodigo del cuadro 2 representa una aplicacion en la cual la logica debera pasar trespruebas antes de que resultadoFinal pueda ser mostrado. El programa ejecuta el metodoA();luego llama al metodoB() solo si metodoA() es exitoso. De igual forma, el metodoC() se ejecutasolo cuando ambos metodos metodoA() y metodoB() son ambos exitosos. Cuando falla algunode los metodos, el programa pone un codigo A’, ’B’, o ’C’ apropiado en codigoError, quizascodigoError sea usado mas tarde en la aplicacion. La logica es difıcil de seguir, y el propositode la aplicacion y la salida usual intentada, mostrar resultadoFinal, se pierde en laberinto desentencias if. Tambien, se pueden facilmente cometer errores de codificacion dentro del programapor el anidamiento complicado, sangrado, y apertura y cierre de llaves.

Comparar la misma logica del programa usando la tecnica orientada al objeto, manejo de erroresde Java mostrada en el cuadro 4. Usando la tecnica try...catch se logran los mismos resultadosque el metodo tradicional, pero las sentencias del programa que hacen el trabajo “verdadero”, lallamada a los metodos A, B, y C y mostrar resultadoFinal, estan puestos juntos, donde su logicaes mas facil de seguir. Los pasos try deberıan usualmente trabajar sin generar errores; despues detodo, los errores son “excepciones”. Es conveniente ver los pasos usuales en un solo lugar, y loseventos excepcionales estan agrupados y puestos fuera de la accion primaria.

try {llamar al metodoA()

llamar al metodoB()

llamar al metodoC()

}catch (error del metodoA()){

poner codigoError a ’A’

}catch (error del metodoB()){

poner codigoError a ’B’

}catch (error del metodoC()){

poner codigoError a ’C’

}

Cuadro 4: Pseudocodigo representando el manejo de excepciones orientada al objeto

Una ventaja del manejo de excepciones orientada al objeto, ademas de la claridad, es la flexibilidadque permite en el manejo de situaciones de error. Cuando un metodo escrito lanza una excepcion, elmismo metodo puede atrapar la excepcion, lo cual no es necesario y en la mayorıa de los programasno se hace. Generalmente no se quiere que un metodo maneje su propia excepcion. En muchoscasos, se quiere que el metodo revise los errores, pero no se quiere hacer que un metodo maneje unerror si este lo encuentra. Otra ventaja con el manejo de excepciones es que se tiene la habilidadpara manejar apropiadamente las excepciones conforme se decide como hacerlo. Cuando se escribeun metodo, este puede llamar otro, atrapar una excepcion lanzada, y se puede decidir que se quierehacer. Los programas pueden reaccionar a excepciones especıficas para sus propositos actuales.

Los metodos son flexibles en parte porque son reusables. Cada aplicacion llamada podrıa necesitarmanejar un error lanzado diferentemente, dependiendo de su proposito. Considerar una aplicacionque usa un metodo que divide valores podrıa necesitar terminar si la division por cero ocurre. Un

17

Page 18: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

programa diferente podrıa querer que el usuario reingrese el dato a ser usado, y un tercer programapodrıa querer forzar la division por uno. El metodo que contiene la sentencia de division podrıalanzar el error, pero cada programa que llama puede asumir la responsabilidad para manejar elerror detectado por el metodo en una forma apropiada.

6. Especificar excepciones que un metodo puede lanzar

Si un metodo lanza una excepcion que no atrapara pero que sera atrapada por un metodo diferente,se debe usar la palabra reservada throws seguida por un tipo Exception en la cabecera del metodo.Esta practica es conocida como especificacion de excepcion.

En la clase ListaPrecios, codigo 9, usada por una empresa para tener una lista de precios delos artıculos que venden, hay solamente cuatro precios y un solo metodo que muestra el precio deun artıculo individual. El metodo mostrarPrecio() acepta un parametro que sera usado como elsubındice del arreglo, pero como el subındice podrıa estar fuera de rango, el metodo contiene unaclausula throws en la lınea 3, reconociendo que podrıa lanzar una excepcion.

1 public class L i s t a P r e c i o s {2 private stat ic f ina l double [ ] p r e c i o = {35 .50 , 67 .80 , 12 . 50 , 3 2 . 2 0} ;3 public stat ic void mostrarPrec io ( int a r t i c u l o ) throws IndexOutOfBoundsException {4 System . out . p r i n t l n ( ”El p r e c i o es $” + p r e c i o [ a r t i c u l o ] ) ;5 }6 }

Codigo 9: La clase ListaPrecios.

La aplicacion AplicacionListaPrecios1, codigo 10, se ha escogido manejar la excepcion en elbloque catch, lıneas 11—13, para mostrar un precio de cero.

1 import java . u t i l . Scanner ;2 public class A p l i c a c i o n L i s t a P r e c i o s 1 {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int a r t i c u l o ;6 System . out . p r i n t ( ” I n g r e s a r e l numero de l a r t ı cu lo >> ” ) ;7 a r t i c u l o = entrada . next Int ( ) ;8 try {9 L i s t a P r e c i o s . mostrarPrec io ( a r t i c u l o ) ;

10 }11 catch ( IndexOutOfBoundsException e r r o r ) {12 System . out . p r i n t l n ( ”El p r e c i o es $0” ) ;13 }14 }15 }

Codigo 10: Clase AplicacionListaPrecios1.

En la aplicacion AplicacionListaPrecios2, codigo 11, el programador ha escogido manejar laexcepcion en el bloque catch, lıneas 12—14, mostrando el precio del ultimo artıculo del arreglo.

18

Page 19: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

1 import java . u t i l . ∗ ;2 public class A p l i c a c i o n L i s t a P r e c i o s 2 {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int a r t i c u l o ;6 f ina l int ARTMAX = 3 ;7 System . out . p r i n t ( ” I n g r e s a r e l numero de l a r t ı cu lo >> ” ) ;8 a r t i c u l o = entrada . next Int ( ) ;9 try {

10 L i s t a P r e c i o s . mostrarPrec io ( a r t i c u l o ) ;11 }12 catch ( IndexOutOfBoundsException e r r o r ) {13 L i s t a P r e c i o s . mostrarPrec io (ARTMAX) ;14 }15 }16 }

Codigo 11: Clase AplicacionListaPrecios2.

Otros programadores escribiendo otras aplicaciones que usen la clase ListaPrecios podrıan escogertodavıa acciones diferentes, pero pueden usar el metodo flexible mostrarPrecio() porque este nolimita la llamada de los metodos de recurso escogidos.

Para la mayorıa de los metodos Java que se escriben no se usa la clausula throws. La mayorıadel tiempo se le permite a Java manejar cualquier excepcion abortando el programa, ya que deotra forma se requerirıa dar instrucciones para manejar cada error posible. Muchas excepcionesnunca tendran que ser explıcitamente lanzadas o atrapadas, ni se tendran que incluir una clausulathrows en la cabecera de los metodos que automaticamente lanzan estas excepciones. Las unicasexcepciones que deberan ser atrapadas o nombradas en una clausula throws son del tipo conocidocomo excepciones comprobadas.

Las excepciones de Java pueden ser categorizadas en dos tipos:

Excepciones no comprobadas. Estas heredan de la clase Error o RuntimeException. Sepueden manejar estas excepciones en los programas, pero no se esta obligado a hacerlo. Porejemplo, dividir por cero es un tipo de RuntimeException, y no se esta obligado a manejaresta excepcion, se puede dejar que el programa termine.

Excepciones comprobadas. Estas excepciones son del tipo donde los programadores podrıananticipar y de las cuales los programas deberıan poderse recuperar. Todas las excepciones queexplıcitamente se lanzen y que desciendan de la clase Exception son excepciones comproba-das.

Los programadores dicen que las excepciones comprobadas estan sujetas al catch o especificamientode requerimientos, lo cual significa que si se lanza una excepcion comprobada desde un metodo, sedebe hacer uno de los siguientes:

Atrapar y manejar la excepcion posible.

Declarar la excepcion en su clausula throws. El metodo llamado puede entonces relanzar laexcepcion a otro metodo que podrıa atraparla o lanzarla otra vez.

19

Page 20: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Es decir, cuando una excepcion es una comprobada, los programas clientes son forzados a negociarcon la posibilidad que una excepcion sera lanzada.

Si se escribe un metodo que explıcitamente lanza una excepcion comprobada que no es capturadadentro del metodo, Java requiere que se use la clausula throws en la cabecera del metodo. Usandola clausula throws no significa que el metodo lanzara una excepcion, todo podrıa ir bien. En vezde esto significa que el metodo podrıa lanzar una excepcion. Se incluye la clausula throws en lacabecera del metodo para que las aplicaciones que usen los metodos esten notificados del potencialde una excepcion.

Nota. La firma del metodo es la combinacion del nombre del metodo y la cantidad, tipo y orden de

los argumentos. La clausula throws no es parte de la firma porque no se puede crear una clase que

contenga metodos multiples que solo difieran en sus clausulas throws; el compilador considera que

los metodos tienen firma identica. Se podrıa decir que la clausula throws es parte de la interfaz del

metodo.

Nota. Un metodo que anule otro no puede lanzar una excepcion a menos que esta lance el mismo tipo

como su padre o una subclase del tipo lanzado de su padre. Estas reglas no aplican a metodos so-

brecargados. Cualquier excepcion podrıa o no ser lanzada de una version de un metodo sobrecargado

sin considerar que excepciones son lanzadas por otras versiones de un metodo sobrecargado.

Para poder usar un metodo a su potencial completo, se debe conocer el nombre del metodo y trespiezas adicionales de informacion:

El tipo regresado por el metodo.

El tipo y numero de argumentos que el metodo requiere.

El tipo y cantidad de excepciones que el metodo lanza.

Para usar un metodo, se debe saber que tipos de argumentos son requeridos. Se puede llamarun metodo sin saber su tipo devuelto, pero no se puede beneficiar de algun valor que el metododevuelva, ademas no se entenderıa el proposito del metodo. De igual forma no se pueden hacerdecisiones coherentes acerca de que hacer en caso de un error si no se sabe que tipos de excepcionesun metodo podrıa lanzar.

Cuando un metodo podrıa lanzar mas de una tipo de excepcion, se puede indicar una lista de lasexcepciones potenciales en la cabecera del metodo separandolas con comas. Como una alternativa,si todas las excepciones descienden del mismo padre, se puede especificar la clase padre mas general.Si el metodo podrıa lanzar una ArithmeticException o una ArrayIndexOutOfBoundsException,se puede solo especificar que el metodo lanza una RuntimeException. Una ventaja de esta tecnicaes cuando el metodo es modificado para incluir RuntimeException mas especıfico en el futuro, lacabecera del metodo no cambiara. Esto ahorra tiempo para los usuarios de los metodos, quienes notendran que modificar sus propios metodos para considerar nuevos tipos RuntimeException.

Una alternativa extrema es especificar que el metodo lance un objeto Exception general, ası todaslas excepciones estan incluidas en una clausula. Con esto se simplifica la especificacion de la ex-cepcion, pero se disfraza la informacion acerca de los tipos especıficos de excepciones que podrıanocurrir, y esta informacion tiene valor para los usuarios de los metodos.

20

Page 21: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

Nota. Se declaran solo excepciones comprobadas. Las excepciones tiempos de ejecucion pueden

ocurrir en cualquier parte del programa, y pueden ser numerosas. Los programas podrıan ser menos

limpios y mas incomodos si se tiene que tener en cuenta las excepciones tiempos de ejecucion en

cada declaracion del metodo. Por lo tanto, el compilador de Java no requiere que se atrape o se

especifiquen excepciones tiempos de ejecucion.

7. Traza de excepciones en la pila de llamadas

Cuando un metodo llama a otro, el sistema operativo de la computadora debera seguir la pista dedonde provino la llamada del metodo, y el control del programa debe regresar al metodo llamadorcuando el metodo llamado este completo. Si el metodoA() llama al metodoB(), el sistema operativotiene que “recordar” regresar al metodoA() cuando el metodoB() termine. De igual forma si elmetodoB() llama al metodoC(). La localidad de memoria conocida como la pila de llamadas esdonde la computadora guarda la lista de la ubicacion del metodo al cual el sistema deba regresar.

Cuando un metodo lanza una excepcion y el metodo no la atrapa, la excepcion es lanzada al siguientemetodo de la pila de llamadas, o al metodo que llamo al metodo ofendido. Si el metodoA() llamaal metodoB(), y el metodoB() llama al metodo metodoC(), y el metodoC() lanza una excepcion,Java primero busca por un bloque catch en el metodoC(). Si ninguno existe, Java busca por lamisma cosa en el metodoB(). Si el metodoB() no tiene un bloque catch, Java busca en metodoA().Si el metodoA() no puede atrapar la excepcion, esta es lanzada a la Maquina Virtual Java, la cualmuestra un mensaje en la pantalla.

La aplicacion DemoTrazaPila, codigo 12, en el metodo main() llama al metodoA(), el cual muestraun mensaje y llama al metodoB(). Dentro del metodoB(), otro mensaje es mostrado y el metodoC()es llamado. En el metodoC(), otro mensaje es mostrado. Luego un arreglo de tres enteros es de-clarado, y el programa intenta mostrar el cuarto elemento del arreglo. El programa compila co-rrectamente, pero un error es detectado cuando el metodoC() intenta acceder el elemento fuera delrango.

21

Page 22: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

1 public class DemoTrazaPila {2 public stat ic void main ( St r ing [ ] a rgs ) {3 metodoA ( ) ;4 }5 public stat ic void metodoA ( ) {6 System . out . p r i n t l n ( ”En e l metodoA ( ) ” ) ;7 metodoB ( ) ;8 }9 public stat ic void metodoB ( ) {

10 System . out . p r i n t l n ( ”En e l metodoB ( ) ” ) ;11 metodoC ( ) ;12 }13 public stat ic void metodoC ( ) {14 System . out . p r i n t l n ( ”En e l metodoC ( ) ” ) ;15 int [ ] a r r e g l o = {0 , 1 , 2} ;16 System . out . p r i n t l n ( a r r e g l o [ 3 ] ) ;17 }18 }

Codigo 12: Clase DemoTrazaPila.

Enseguida se muestra la salida cuando se ejecuta DemoTrazaPila que tiene tres mensajes, indi-cando el orden en el que fueron llamados los metodos metodoA(), metodoB() y metodoC(). Sinembargo, cuando el metodoC() intenta acceder el elemento fuera de rango en el arreglo, una excep-cion ArrayIndexOutOfBoundsException es automaticamente lanzada. El mensaje de error generamuestra que la excepcion ocurrio en la lınea 16 del archivo en el metodoC(), el cual fue llamado enla lınea 11 del archivo por el metodoB(), el cual fue llamado en la lınea 7 por el metodoA(), el cualfue llamado por el metodo main() en la lınea 3 del archivo. Usando la lista de mensajes de error,se podrıa rastrear el lugar donde el error fue generado. Por supuesto, en una aplicacion mas grandaque contenga miles de lıneas de codigo, la lista del historial de seguimiento de la pila podrıa sermas util.

En el metodoA()

En el metodoB()

En el metodoC()

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3

at DemoTrazaPila.metodoC(DemoTrazaPila.java:16)

at DemoTrazaPila.metodoB(DemoTrazaPila.java:11)

at DemoTrazaPila.metodoA(DemoTrazaPila.java:7)

at DemoTrazaPila.main(DemoTrazaPila.java:3)

Cuando un programa usa varias clases, la desventaja es que el programador encuentra difıcil en-contrar la fuente original de una excepcion.

El metodo getMessage() de Throwable se usa para obtener informacion de un objeto Exception.Otro metodo util de Exception es el metodo printStackTrace(). Cuando se atrapa un objetoException, se puede llamar printStackTrace() para mostrar una lista de metodos en la pila dellamadas y determinar el lugar de la sentencia que causo la excepcion.

La aplicacion DemoTrazaPila2, codigo 13, en la cual el metodo printStackTrace() produce unseguimiento del camino tomado por el lanzamiento de una excepcion. La llamada al metodoB()

22

Page 23: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

ha sido puesta en un bloque try para que la excepcion pueda ser capturada. En vez de lanzar laexcepcion al sistema operativo, la aplicacion atrapa la excepcion, muestra la lista del historial deseguimiento de la pila, y continua la ejecucion.

1 public class DemoTrazaPila2 {2 public stat ic void main ( St r ing [ ] a rgs ) {3 metodoA ( ) ;4 }5 public stat ic void metodoA ( ) {6 System . out . p r i n t l n ( ”En e l metodoA ( ) ” ) ;7 try {8 metodoB ( ) ;9 }

10 catch ( ArrayIndexOutOfBoundsException e r r o r ) {11 System . out . p r i n t l n ( ”En metodoA ( ) − Seguimiento de l a p i l a : ” ) ;12 e r r o r . pr intStackTrace ( ) ;13 }14 System . out . p r i n t l n ( ”metodoA ( ) termina normalmente . ” ) ;15 System . out . p r i n t l n ( ”La a p l i c a c i on podrıa cont inuar desde e s t e punto . ” ) ;16 }17 public stat ic void metodoB ( ) {18 System . out . p r i n t l n ( ”En e l metodoB ( ) ” ) ;19 metodoC ( ) ;20 }21 public stat ic void metodoC ( ) {22 System . out . p r i n t l n ( ”En e l metodoC ( ) ” ) ;23 int [ ] a r r e g l o = {0 , 1 , 2} ;24 System . out . p r i n t l n ( a r r e g l o [ 3 ] ) ;25 metodoB ( ) ;26 }27 }

Codigo 13: Clase DemoTrazaPila2.

Actividad 6. Ejecutar la aplicacion DemoTrazaPila2 para revisar que la aplicacion no terminaabruptamente.

Generalmente no se quiere poner una llamada al metodo printStackTrace() en un programaterminado. El usuario tıpico de la aplicacion no tiene interes en los mensajes crıtpico que sonmostrados. Sin embargo, mientras se esta desarrollando una aplicacion, printStackTrace() puedeser una herramienta util para diagnosticar los problemas de la clase.

8. Creacion de clases Exception propias

Java proporciona mas de 40 categorıas de Exception que se pueden usar en los programas. Perohay situaciones que no fueron consideradas en Java, por ejemplo, se podrıa querer declarar unaException cuando el saldo bancario es negativo o cuando un participante externo intenta acce-der su cuenta de correo electronico. Diversas organizaciones tienen reglas especıficas para datosexcepcionales; por ejemplo, un numero de empleado no debera exceder tres dıgitos, o un salariopor hora no debera ser menor que el salario mınimo legal. Por supuesto, se pueden manejar estas

23

Page 24: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

situaciones potenciales de error con sentencias if, pero Java tambien permite crear sus propiasclases Exception.

Para crear su propia clase Exception lanzable, se debe extender una subclase de Throwable.Throwable tiene dos subclases, Exception y Error, las cuales son usadas para distinguir entreerrores recuperables e irrecuperables. Como siempre se quiera que las excepciones propias se pue-dan recuperar entonces las clases se deberıan extender de la clase Exception. Se puede extendercualquier subclase Exception existente, como ArithmeticException o NullPointerException,pero generalmente se quiere heredar directamente de Exception. Cuando se crea una subclaseException, es una convencion terminar el nombre con Exception.

La clase Exception contiene cuatro constructores que son:

Exception(). Construye un nuevo objeto Exception con null como su mensaje detallado.

Exception(String mensaje). Construye un nuevo objeto Exception con el mensaje deta-llado especificado.

Exception(String mensaje, Throwable causa). Construye un nuevo objeto Exception

con el mensaje detallado especificado y causa.

Exception(Throwable causa). Construye un nuevo objeto Exception con la causa especi-ficada y un mensaje detallado de causa.toString(), la cual tıpicamente contiene la clase ymensaje detallado de causa, o null si el argumento de la causa es null.

La clase SaldoAltoException, codigo 14, tiene un constructor que contiene una sola sentenciaque pasa una descripcion de un error al constructor padre Exception. Este String podrıa serrecuperada si se llama al metodo getMessage() con un objeto SaldoAltoException.

1 public class SaldoAltoExcept ion extends Exception {2 public SaldoAltoExcept ion ( ) {3 super ( ”El sa ldo de l c l i e n t e e s t a a l t o ” ) ;4 }5 }

Codigo 14: Clase SaldoAltoException.

En la clase CuentaCliente, codigo 15, se usa SaldoAltoException. La cabecera del constructorCuentaCliente indica que podrıa lanzar una instancia SaldoAltoException sin nombre, en el casode que el saldo usado como argumento para el constructor exceda un lımite.

24

Page 25: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

1 public class CuentaCl iente {2 private int numCuenta ;3 private double sa ldo ;4 public stat ic double LIM CRED SUP = 20000 . 00 ;5 public CuentaCl iente ( int num, double s a l ) throws SaldoAltoExcept ion {6 numCuenta = num;7 sa ldo = s a l ;8 i f ( sa ldo > LIM CRED SUP )9 throw new SaldoAltoExcept ion ( ) ;

10 }11 }

Codigo 15: Clase CuentaCliente.

Nota. En la clase CuentaCliente se podrıa escoger instanciar un SaldoAltoException con nombre

y lanzarlo cuando el balance exceda el lımite de credito. Se mejora el rendimiento del programa

esperando e instanciando un objeto anonimo solo cuando sea necesario.

En la aplicacion UsaCuentaCliente, 16, se le pide al usuario un numero de cuenta y un saldo.Despues de que los valores son dados, se intenta construir un objeto CuentaCliente en un bloquetry, como se ve en la lınea 12. Si el intento es exitoso, es decir, el constructor CuentaCliente nolanza una Exception, entonces la informacion del objeto es mostrada en cuadro de dialogo. Pero si elconstructor lanza una SaldoAltoException, el bloque catch, lıneas 16—20, lo recibe y muestra unmensaje. Una aplicacion diferente podrıa mostrar el valor regresado por el metodo getMessage(),construir un objeto CuentaCliente con un saldo menor, o construir un tipo diferente de objeto elpermita una saldo mayor.

1 import javax . swing . ∗ ;2 public class UsaCuentaCliente {3 public stat ic void main ( St r ing [ ] a rgs ) {4 int num;5 double sa ldo ;6 St r ing entrada ;7 entrada = JOptionPane . showInputDialog ( null , ” I n g r e s a r numero de cuenta ” ) ;8 num = I n t e g e r . pa r s e In t ( entrada ) ;9 entrada = JOptionPane . showInputDialog ( null , ” I n g r e s a r e l sa ldo que se debe” ) ;

10 sa ldo = Double . parseDouble ( entrada ) ;11 try {12 CuentaCl iente cc = new CuentaCl iente (num, sa ldo ) ;13 JOptionPane . showMessageDialog ( null , ” C l i en t e # ” +14 num + ” t i e n e un sa ldo de $” + sa ldo ) ;15 }16 catch ( SaldoAltoExcept ion esa ) {17 JOptionPane . showMessageDialog ( null , ” C l i en t e # ” +18 num + ” t i e n e un sa ldo de $” + sa ldo +19 ” e l cua l es mayor que e l l ımite de l c r e d i t o ” ) ;20 }21 }22 }

Codigo 16: Aplicacion UsaCuentaCliente.

25

Page 26: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

En vez de codificar los mensajes de error en las clases de excepcion, como se muestra en el codigo16, se podrıa considerar crear un catalogo de mensajes posibles para usar. Esta forma da variasventajas:

Todos los mensajes son guardados en una localidad en vez de estar dispersos por todo elprograma, haciendo mas facil verlos y modificarlos.

La lista de errores posibles sirve como una fuente de documentacion, listando problemaspotenciales cuando se ejecute la aplicacion.

Otras aplicaciones podrıan querer usar el mismo catalogo de mensajes.

Si la aplicacion sera usada mundialmente, se puede proporcionar mensajes en multiples len-guajes, y otros programadores pueden usar la version que es apropiada para su paıs.

Nota. Se puede lanzar cualquier tipo de excepcion en cualquier momento, no solo las excepciones

de su propia creacion. Por ejemplo, dentro de cualquier programa se puede codificar throw(new

RuntimeException());. Se podrıa querer hacerlo solo con una buena razon porque Java maneja

RuntimeException por usted parando el programa. Como no se puede anticipar cada error posible,

la respuesta automatica de Java es frecuentemente el mejor curso de la accion.

No se deberıa crear una cantidad excesiva de tipos de excepcion especiales para sus clases, porqueel ambiente de desarrollo de Java ya contiene un clase Exception que atrapara el error. Los tiposException adicionales agregan complejidad para otros programadores que usaran sus clases. Sinembargo, cuando clases Exception apropiadas y especializadas proporcionan una forma elegantepara manejar las situcaciones de error, permiten separar el codigo de manejo de error de la secuenciade eventos no excepcionales y usuales. Permiten a los clientes de sus clases manejar situacionesexcepcionales de la forma mas adecuada para su aplicacion.

9. Uso de afirmaciones

Algunos errores de logica no causan que un programa termine pero producen resultados incorrectos.Por ejemplo, si un programa de pago debe determinar el pago multiplicando horas trabajados porel pago por hora, pero si inadvertidamente se dividieron los numeros, no ocurre un error en tiempode ejecucion y no se lanza excepcion, pero la salida es incorrecta. Una afirmacion es una capacidaddel lenguaje Java que puede ayudar a detectar tales errores de logica para depurar el programa.Se usa la sentencia assert para crear una afirmacion; cuando se usa una sentencia assert, seestablece una condicion que deberıa ser true, y Java lanza una assertionError cuando no.

La sintaxis de la sentencia assert es:

assert expresionBooleana : mensajeErrorOpcional

La expresion booleana en la sentencia assert debera ser siempre true si el programa esta traba-jando correctamente. El mensajeErrorOpcional es mostrado si la expresionBooleana es false.

26

Page 27: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

La aplicacion ParImpar, codigo 17, pide a un usuario un numero y lo pasa a un metodo quedetermina si un valor es par. Dentro del metodo esPar(), el residuo es tomado cuando el parametropasado es dividido por 2. Si el residuo despues de dividir por 2 es 1, resultado es puesto a false.Por ejemplo, 1, 3, y 5 todos son impares, ya que todos los resultados dan un valor de 1 cuando %2 es aplicado a estos. Si el residuo despues de dividir por 2 no es 1, resultado es puesto a true.Por ejemplo, 2, 4, y 6 todos son pares, todos tienen un 0 de residuo cuando % 2 es aplicado a ellos.

1 import java . u t i l . Scanner ;2 public class ParImpar {3 public stat ic void main ( St r ing [ ] a rgs ) {4 Scanner entrada = new Scanner ( System . in ) ;5 int numero ;6 System . out . p r i n t ( ” I n g r e s a r un numero >> ” ) ;7 numero = entrada . next Int ( ) ;8 i f ( esPar ( numero ) )9 System . out . p r i n t l n ( numero + ” es par” ) ;

10 else11 System . out . p r i n t l n ( numero + ” es impar” ) ;12 }13 public stat ic boolean esPar ( int numero ) {14 boolean r e s u l t a d o ;15 i f ( numero % 2 == 1)16 r e s u l t a d o = fa l se ;17 else18 r e s u l t a d o = true ;19 return r e s u l t a d o ;20 }21 }

Codigo 17: ParImpar.

La siguiente salida se muestra correcta excepto en las dos ultimas ejecuciones. Los valores -5 y -7son clasificados como pares sin embargo son impares. Una afirmacion podrıa ayudar a depurar laaplicacion.

$ java ParImpar

Ingresar un numero >> 4

4 es par

$ java ParImpar

Ingresar un numero >> 5

5 es impar

$ java ParImpar

Ingresar un numero >> -4

-4 es par

$ java ParImpar

Ingresar un numero >> -5

-5 es par

$ java ParImpar

Ingresar un numero >> -7

-7 es par

27

Page 28: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

En el codigo 18 se tiene una nueva version del metodo es esPar() al cual se le ha agregado lasentencia assert en la lınea 7 (ademas las llaves). La sentencia afirma que cuando el residuo deun numero dividido por 2 no es 1, debera ser 0. Si la expresion no es true, un mensaje es creadousando los valores de numero y su residuo despues de dividir por 2.

1 public stat ic boolean esPar ( int numero ) {2 boolean r e s u l t a d o ;3 i f ( numero % 2 == 1)4 r e s u l t a d o = fa l se ;5 else {6 r e s u l t a d o = true ;7 a s s e r t numero % 2 == 0 : numero + ” % 2 es ” + numero % 2 ;8 }9 return r e s u l t a d o ;

10 }

Codigo 18: El metodo defectuoso esPar con una afirmacion.

Si se agrega la afirmacion entonces al momento de ejecutar el programa se debe usar la opcion -ea

enable assertion para que sea lanzada la excepcion cuando la afirmacion no sea verdadera.

Al ejecutar el programa ParImpar y con el valor -5, el programa muestra el mensaje de que unaAssertionError fue lanzada y que el valor de -5 % 2 es -1, no 1 como se habıa asumido. El operadorresiduo da un valor negativo cuando el primer operando es negativo.

Los ajustes que podrıan realizarse al codigo para que muestre la informacion correctamente sonalguno de los siguientes:

1. Calcular el valor absoluto del parametro numero del metodo esPar() antes de usar el operadorresiduo:

numero = Math.abs(numero);

2. Cambiar la sentencia de seleccion para probar por valores pares primero revisando si numero %0 es cero.

if (numero % 2 == 1)

resultado = true;

else

resultado = false;

3. Otras opciones son: mostrar un mensaje de error cuando valores negativos sean encontrados,invertir los valores del resultado cuando el parametro sea negativo, o lanzar una excepcion.

Un programador experimentado podrıa encontrar el error sin usar una afirmacion. Quizas por quesabıa que al aplicarlo con un valor negativo el resultado es negativo. O metiendo sentencias paramostrar valores en puntos estrategicos en el programa, pero despues de que el error es encontrado,las sentencias extras puestas deben ser quitadas. En cambio, cualquier sentencia assert puede serdejada, y si no se usa la opcion -ea al ejecutar el programa, el usuario no vera evidencia del uso

28

Page 29: Manejo de Excepciones - computo.fismat.umich.mxcomputo.fismat.umich.mx/.../actividades/manejo_excepciones.pdf · varios tipos de excepciones potenciales: Podr a emitir un comando

de sentencias assert. Colocando sentencias assert en lugares clave del programa puede reducir eltiempo de desarrollo y depuracion.

No se quieren usar afirmaciones para revisar cada tipo de error que podrıa ocurrir en un programa.Si se quiere asegurar que un usuario ingrese datos numericos, se deberıa usar las tecnicas de manejode excepciones que dan los medios para que el programa se recupere de ese error. Si se quiereasegurar que los datos caen dentro de un cierto rango, se deberıa usar una decision o un ciclo. Lasafirmaciones son de ayuda en la etapa de desarrollo de un programa, no cuando esta en producciony en las manos de los usuarios.

29