Logo Studenta

Java-Excepciones

¡Estudia con miles de materiales!

Vista previa del material en texto

Java: control de excepciones
Franco Guidi Polanco
Escuela de Ingeniería Industrial
Pontificia Universidad Católica de Valparaíso, Chile
fguidi@ucv.cl
Actualización: 07 de marzo de 2007
09-03-2007Franco Guidi Polanco 2
Introducción
Una excepción es un evento que ocurre durante la 
ejecución de un programa, y que interrumpe su flujo de 
control normal. Normalmente se encuentran asociadas a 
“errores”.
Los errores pueden tener distintos orígenes: falla del disco 
duro, problemas en la red, problemas de programación (ej.
división por cero), etc.
09-03-2007Franco Guidi Polanco 3
Detección de errores
Cuando ocurre un error durante la ejecución de un método en Java se 
genera un objeto excepción que es enviado al ambiente de ejecución. El 
flujo de control normal del programa es interrumpido.
El objeto excepción contiene información relativa al error, incluyendo el 
tipo del mismo y el estado del programa al momento de haberse 
producido.
Cuando se genera el objeto excepción, 
el ambiente de ejecución busca 
en el stack de llamadas a métodos 
alguno que sea capaz de manejar 
la excepción (exception handler). 
Si no lo encuentra, la JVM se hace cargo 
de él, y el programa termina con 
un mensaje de error.
JVM
método 1
método n
Excepción
St
ac
k
m
ét
od
os
método 2
…
09-03-2007Franco Guidi Polanco 4
Ejemplo 1
Un caso de división por cero:
public class Division{
public static void main(String[] arg) {
Par par = new Par( 100, 0 );
par.divide();
System.out.println(“Fin programa”);
}
}
public class Par {
int x, y;
public Par(int x, int y ){
this.x = x;
this.y = y;
}
public int divide() {
return x/y;
}
}
El objeto de la clase Par
realizará una división 
por cero
Clase Par, recibe dos 
números enteros
y permite obtener el 
cuociente entre ellos
09-03-2007Franco Guidi Polanco 5
Ejemplo 1: Stack de llamadas a métodos
El método main invoca al método divide del objeto de la clase Par.
Durante la ejecución del método divide se genera una excepción.
Java Virtual Machine
main
divide
...
par.divide();
...
...
return x/y;
... (y = 0)
09-03-2007Franco Guidi Polanco 6
Ejecución del ejemplo 1
Clase de excepción:
java.lang.ArithmeticException
Información:
/ by zero (división por cero)
Stack de llamadas de métodos:
1. Método divide de la clase Par (archivo Par.java, línea 11)
…llamado por…
2. Método main de la clase Division (archivo Division.java, línea 6)
09-03-2007Franco Guidi Polanco 7
La jerarquía de excepciones
Object
Throwable
Exception
RuntimeException
…
…
Error
…
09-03-2007Franco Guidi Polanco 8
Opciones en el control de excepciones
Frente a un determinado tipo de excepción un método 
puede:
Lanzar la excepción fuera de él, para traspasar al método 
invocante la responsabilidad de tratar la excepción; o en caso de 
ser el primer método del stack de llamadas, traspasar la 
responsabilidad a la JVM.
Capturar la excepción, y proveer un flujo de control alternativo.
JVM
main
divide
Excepción
St
ac
k
m
ét
od
os
09-03-2007Franco Guidi Polanco 9
Control de excepciones: lanzamiento de una excepción
Para indicar que un método traspasará la responsabilidad 
del control de excepciones al método llamante, se debe 
usar la cláusula throws en la declaración del método, 
seguida por el nombre de la excepción:
Ejemplo:
public boolean startPlaying() throws SoundException {
...
}
Nombre
excepción
09-03-2007Franco Guidi Polanco 10
Control de excepciones: lanzamiento de una excepción 
(cont.)
Un ejemplo clásico: lectura de datos de la consola
import java.io.* ;
public class Factorial {
public static void main( String arg[ ] ) throws IOException {
int número=0, i=1, fact=1;
BufferedReader lector = new BufferedReader( new InputStreamReader( System.in ) );
String ingresado=null;
System.out.println( "Ingrese número para cálculo de factorial: " );
ingresado = lector.readLine( );
número = Integer.parseInt( ingresado );
while( i <= número ) {
fact = fact * i;
i++;
}
System.out.println( "El factorial de " + número + " es " + fact );
} // Fin método main
} // Fin clase
09-03-2007Franco Guidi Polanco 11
Control de excepciones: captura de una excepción
Las excepciones pueden ser capturadas y manejadas 
usando bloques try, catch y finally (operan en 
conjunto)
El bloque try debe incluir las instrucciones que pueden generar la 
excepción que se desea manejar. Debe ser seguido por al menos 
un bloque catch o un bloque finally.
El bloque catch debe seguir al bloque try, y debe contener las 
instrucciones que serán ejecutadas en caso de generarse una 
excepción.
El bloque finally incluye las instrucciones que deberán 
ejecutarse independientemente de la generación (o ausencia) de 
una excepción (normalmente usados para liberar recursos).
09-03-2007Franco Guidi Polanco 12
Control de excepciones: captura de una excepción (cont.)
Formato general:
try {
// instrucciones que pueden fallar
…
} catch (Tipo_excepción1 nombre_variable){
// instrucciones a ejecutar si se produce 
// una excepción tipo 1
…
} catch (Tipo_excepción2 nombre_variable){
// instrucciones a ejecutar si se produce 
// una excepción tipo 2
…
} catch (Tipo_excepciónN nombre_variable){
// instrucciones a ejecutar si se produce 
// una excepción tipo N
…
} finally{
// instrucciones a ejecutar siempre 
}
El tipo de excepción 
(Tipo_Excepción1, 
Tipo_Excepción2, etc.) 
representa la clase de 
excepción que se puede 
generar en el bloque try
que interesa capturar y 
controlar.
El orden de los catch es 
importante: las subclases 
de excepciones deben ser 
especificadas antes de 
sus superclases 
Al producirse una 
excepción sólo uno de 
los bloques catch será 
ejecutado
09-03-2007Franco Guidi Polanco 13
Control de excepciones: captura de una excepción (cont.)
(Nuevamente) el ejemplo clásico:
import java.io.* ;
public class Factorial {
public static void main( String arg[ ] ){
int número=0, i=1, fact=1;
BufferedReader lector = new BufferedReader( new InputStreamReader( System.in ) );
String ingresado=null;
System.out.println( "Ingrese número para cálculo de factorial: " );
try {
ingresado = lector.readLine( );
número = Integer.parseInt( ingresado );
while( i <= número ) {
fact = fact * i;
i++;
System.out.println( "El factorial de " + número + " es " + fact );
}
} catch( IOException e ) {
System.out.println( "Error de input." );
}
} // Fin método main
} // Fin clase
09-03-2007Franco Guidi Polanco 14
Ejemplo 2: captura de una excepción
En este caso la 
excepción es 
interceptada en el 
método divide
public class Division{
public static void main(String[] arg) {
Par par = new Par( 100, 0 );
int res = par.divide();
System.out.println( "El cuociente es: " + res );
}
}
public class Par {
int x, y;
public Par(int x, int y ){
this.x = x;
this.y = y;
}
public int divide() {
try{ 
return x/y;
}catch(ArithmeticException e){
return 999999999;
}
}
}
Nota: en el ejemplo es 
discutible la decisión de 
retornar esta constante en 
caso de error en la división
09-03-2007Franco Guidi Polanco 15
Ejecución del ejemplo 2
A pesar del error el programa completa su ejecución 
normalmente:
¿Qué ocurre?
La excepción se produce en el método divide() de la clase Par, 
dentro del bloque try. Esta excepción es capturada en el bloque 
catch, y el código escrito en este último es ejecutado.
09-03-2007Franco Guidi Polanco 16
Información relacionada con la excepción
Toda instancia de excepción tiene un método 
printStackTrace, que imprime el stack de llamadas de 
métodos al momento de generarse.
Este método puede ser utilizado para proporcionar 
información relacionada con la excepción dentro del bloque 
catch correspondiente:
try {
// instrucciones que pueden fallar
…
} catch (Tipo_excepción nombre_variable){
nombre_variable.printStackTrace();
}
09-03-2007Franco Guidi Polanco 17
Ejemplo 3: impresión de la información asociada a la 
excepción
El objeto excepción es 
referenciado al interior 
del bloque catch por 
medio de la variable e
Se invoca el método
printStackTracesobre el objeto excepción
1 public class Division{
2 public static void main(String[] arg) {
3 Par par = new Par( 100, 0 );
4 int res = par.divide();
5 System.out.println( "El cuociente es: " + res );
6 }
7 }
1 public class Par {
2 int x, y; 
3 public Par(int x, int y ){
4 this.x = x;
5 this.y = y;
6 }
7 public int divide() {
8 try{ 
9 return x/y;
10 }catch(ArithmeticException e){
11 e.printStackTrace();
12 return 999999999;
13 }
14 }
15 }
09-03-2007Franco Guidi Polanco 18
Ejecución del ejemplo 3
El programa ahora indica el tipo de excepción y lugar 
donde ésta se produjo:
Notar que el programa termina su ejecución normalmente.
09-03-2007Franco Guidi Polanco 19
La clase RuntimeException
Representa excepciones comunes que se presentan en la 
JVM durante la ejecución de programas. Ejemplo: 
NullPointerException.
Debido a la ubicuidad de este tipo de excepciones, el 
compilador permite no especificar el mecanismo de control 
de las RuntimeExceptions: cuando este mecanismo no 
es especificado, estas excepciones serán lanzadas fuera del 
método actual.
RuntimeException
NullPointerException
09-03-2007Franco Guidi Polanco 20
La clase RuntimeException (cont.)
Ejemplo: ArithmeticException es subclase de 
RuntimeException. Por tanto las siguientes 
implementaciones de la clase Par son equivalentes:
public class Par {
int x, y;
public Par(int x, int y ){
this.x = x;
this.y = y;
}
public int divide() 
throws ArithmeticException {
return x/y;
}
}
public class Par {
int x, y;
public Par(int x, int y ){
this.x = x;
this.y = y;
}
public int divide() {
return x/y;
}
}
09-03-2007Franco Guidi Polanco 21
Crear nuevas excepciones
Se pueden crear nuevas excepciones extendiendo la clase 
Exception o una de sus subclases.
La clase Exception ofrece distintos constructores que 
pueden ser referenciados desde las subclases. Los más 
utilizados son:
public Exception(): inicializa la excepción con valores de 
default (mensaje nulo)
public Exception(String mensaje): inicializa la excepción 
con el mensaje recibido como parámetro.
Nota: la clase RuntimeException también puede ser 
extendida.
09-03-2007Franco Guidi Polanco 22
Crear nuevas excepciones (cont.)
Ejemplo:
Convención: el nombre de las excepciones termina en la 
palabra “Exception”
public class UnsupportedMediaException extends Exception{
public UnsupportedMediaException(){
super( “The selected media is not supported.” );
}
}
09-03-2007Franco Guidi Polanco 23
Lanzamiento de una excepción
Una excepción puede ser lanzada en cualquier parte del 
código usando la instrucción throw acompañada de la 
referencia a un objeto excepción:
Ejemplo:
throw new NombreExcepción( parámetros_constructor )
public void saveData throws UnsupportedMediaException{
...
if( !isCompatible( requestedMedia ) )
throw new UnsupportedMediaException();
...
}
09-03-2007Franco Guidi Polanco 24
Ejemplo 4: creación y lanzamiento de excepciones
public class Recorder {
String media;
public Recorder( String mediaType ){
media = mediaType;
}
public void saveOn( String mediaType ) throws UnsupportedMediaException{
if( media.equals( mediaType ) )
System.out.println( "Saving." );
else
throw new UnsupportedMediaException();
}
}
public class Test{
public static void main(String[] arg) throws UnsupportedMediaException {
Recorder r = new Recorder( "CD" );
r.saveOn( "DVD" );
System.out.println( "Saved." );
}
}
public class UnsupportedMediaException extends Exception {
public UnsupportedMediaException() {
super( "The selected media is not supported" );
}
}
09-03-2007Franco Guidi Polanco 25
Ejecución del ejemplo 4
La excepción definida se comporta como cualquier 
otra excepción:
09-03-2007Franco Guidi Polanco 26
Ejercicio
Se pide crear la clase Temperature, para registrar 
temperaturas en grados Celsius (ºC) y Kelvin (ºK). 
Una instancia de la clase deberá almacenará un valor de 
temperatura y lo retornará en cualquiera de las escalas. 
Para ello la clase deberá ofrecer los métodos setC y setK
para establecer valores en ºC y ºK, y los métodos getC y 
getK para retornar los valores en ºC y ºK, 
respectivamente.
Notar que no es físicamente posible admitir temperaturas 
inferiores a los 0ºK, por lo tanto será necesario generar una 
excepción (IllegalTemperatureException) cuando un 
valor fuera de rango trate de ser ingresado.
Genere las clases indicadas, y una aplicación que permita 
ingresar valores y visualizarlos. 
09-03-2007Franco Guidi Polanco 27
Discusión
Considere los siguientes ejemplos:
Una clase CuentaCorriente (que maneja una 
cuenta bancaria) no debe admitir giros mayores que 
el saldo disponible. En caso de ser inadmisible el 
giro, éste podría ser impedido:
• Retornado false en el método que efectúa el giro.
• Generando una excepción en el método que efectúa el 
giro.
En la clase Temperature del ejemplo anterior se 
genera una excepción cuando se trata de establecer 
una temperatura inválida. Alternativamente se podría 
haber obviado la creación de la excepción, y haber 
retornado falso en los métodos setK y setC. 
¿Cuándo conviene generar excepciones? 
09-03-2007Franco Guidi Polanco 28
Excepciones: caso del Ariane 5
Vuelo 501, 4 de Junio de 1996, autodestrucción en 
H0 +39 :
Costo: 500 millones de dólares
09-03-2007Franco Guidi Polanco 29
Excepciones: caso del Ariane 5 (cont.)
Sistema de control de vuelo:
SRI: Inertial
Reference System
OBC: On-Board
Computer
OBC-1 OBC-2
MOTORES
Lecturas de giroscopios y acelerómetros
SRI-1 SRI-2
Bus de datos
Plataforma de
referencia inercial
Servo-válvulas y 
actuadores hidráulicos
09-03-2007Franco Guidi Polanco 30
Excepciones: caso del Ariane 5 (cont.)
Reporte del equipo de investigación sobre la falla del vuelo 501:
Aproximadamente en el instante H0 +39 segundos, el Ariane 5 comenzó 
a desintegrarse debido a esfuerzos aerodinámicos excesivos ocasionados 
por un ángulo de ataque inapropiado. Esto condujo a la separación de 
los propulsores auxiliares respecto del cuerpo principal de la nave, por lo 
que se gatilló el mecanismo de autodestrucción del cohete. 
Este ángulo de ataque resultó ser consecuencia de una completa 
desalineación entre las toberas de los propulsores auxiliares y aquella del 
motor principal.
La desalineación de las toberas fue comandada por el OBC a partir de 
información transmitida por el SRI-2. Parte de estos datos no contenían 
información de vuelo, sino un patrón de diagnóstico del SRI, el cual fue 
interpretado como información de vuelo. 
La razón por la cual el SRI-2 no envió datos reales es que la unidad se 
había declarado en falla por una excepción de software.
09-03-2007Franco Guidi Polanco 31
Excepciones: caso del Ariane 5 (cont.)
El OBC no pudo acceder al SRI-1 porque este se había desactivado
algunos milisegundos antes por la misma razón que el SRI-2.
La excepción interna en el software del SRI fue ocasionada durante la 
ejecución de una instrucción de conversión de un valor en formato 
punto flotante de 64 bits a entero con signo de 16 bits, en 
circunstancias que el valor excedía la capacidad del tipo entero. La 
operación de conversión no estaba protegida, aún cuando asignaciones 
de variables similares sí lo estaban.
El valor que se intentó convertir correspondía a la magnitud de la 
variable HB (desviación horizontal), significativa sólo durante la fase de 
alineación previa al despegue. Sin embargo, esta función de cálculo se 
mantuvo operativa durante 40 segundos tras el despegue por un 
requerimiento en el diseño del Ariane 4, no presente en el Ariane 5 (el 
diseño del SRI de ambas naves era en práctica idéntico).
La conversión del valor de la variable HB no estaba protegida porque el 
Ariane 4 realizaba una trayectoria inicial distinta a la del Ariane 5, en la 
cual dicha variable nunca tomaría valores fuera del rango esperado.
09-03-2007Franco Guidi Polanco 32
Excepciones: caso del Ariane 5 (cont.)
Comentarios:
La operación inválida generaba correctamente una excepción. Sin 
embargo, el mecanismo de gestión de excepcionesno fue diseñado 
para responder adecuadamente.
El mecanismo de tolerancia a fallas del Ariane 5 estaba concebido 
para tratar fallas aleatorias (por ej. malfuncionamiento del 
hardware de uno de los computadores), no errores de diseño 
(ambas SRI experimentaron el mismo comportamiento al momento 
de producirse la falla).
El equipo de investigación sobre el accidente sugirió cambiar el
enfoque de desarrollo utilizado hasta entonces, “el software se 
considera correcto hasta que se demuestra que falla”, por el 
enfoque “se asume que el software es defectuoso hasta que, tras 
aplicar métodos aceptados como buenas prácticas, se logre 
demostrar que está correcto”.

Otros materiales