Las excepciones
Objetivos del capítulo
El objetivo de este capítulo es aprender las herramientas que permite tratar los errores (excepciones) que se puedan producir a lo largo de la ejecución de un programa.
Mecanismo de las excepciones
1. Entender los mensajes
public class A
{
private int x, y, z;
public A(int a, int b)
{
x = a;
y = b;
z = x / y;
}
}
La ejecución de la instrucción z = x / y del constructor de la clase A puede provocar un error si la propiedad y vale 0 (cero). En este caso, la máquina virtual instancia un objeto de la clase ArithmeticException e interrumpe la ejecución del constructor.
Ejemplo
public class Exception01
{
public static void main(String argv[])
{
A a = new A(10, 0);
}
}
A continuación se muestra el resultado de la ejecución de este programa:
Los «at» del mensaje de error indican la pila de los métodos llamados.
El error se produce en la ejecución del constructor (<init>) de la clase A, llamado en el método main() de la clase Exception01. Entre paréntesis, figura el nombre del archivo origen con el número de la fila donde se produce el error: fila 9 del constructor, fila 5 del método main().
2. Excepciones monitorizadas, excepciones no monitorizadas
a. Ejemplo
El siguiente programa «oculta» dos excepciones:
import herramientasMG.varios.*;
public class MonitorizadaNoMonitorizada
{
public static void main(String argv[])
{
int numero;
System.out.print("Rellenar un número entero: ");
numero = Teclado.readInt();
System.out.println("\nNúmero introducido: " + numero);
}
}
La que se «oculta» de peor manera se detecta por el compilador:
El método readInt() de la clase Teclado es susceptible de emitir un error de tipo IOException (paquete java.io). Este error es un error...
Ejemplos de utilización de las excepciones
1. Clase Fraccion
Esta clase se utiliza en todos los ejemplos de la sección.
public class Fraccion
{
private int numerador;
private int denominador;
public Fraccion(int numerador, int denominador)
{
this.numerador = numerador;
this.denominador = denominador;
}
public int parteEntera()
{
return numerador / denominador;
}
public String toString()
{
if (denominador!= 1)
{
return numerador + " / " + denominador;
}
else
{
return "" + numerador;
}
}
}
El método parteEntera() es susceptible de provocar una ArithmeticException si el denominador vale 0.
2. Introducir el numerador y el denominador en un bloque try
Cada llamada al método readInt() de la clase Teclado puede emitir una NumberFormatException.
public class Ejemplo1
{
public static void main(String argv[]) throws IOException
{ ...
Creación y lanzamiento de una excepción
Todas las excepciones de los ejemplos anteriores se han creado por la máquina virtual.
Crear una excepción es instanciar un objeto de una clase que hereda de la clase Exception.
Para que la excepción pueda ser capturada (catch), se tiene que lanzar (throw). Esta es la función de la palabra clave throw.
La instrucción throw new TypeException(); lanza una excepción de tipo TypeException.
La excepción que se acaba de crear y lanzar por el programador ahora se puede tratar como cualquier excepción, por un catch o un throws.
Creación de una nueva clase de excepción
Una clase de excepción es una clase que hereda de la clase Exception.
Ejemplo
public class DenominadorNulException extends Exception
{
public DenominadorNulException()
{
super("El denominador es nulo.");
}
}
Se quiere impedir la instanciación de una Fraccion, cuyo denominador vale 0. Es posible modificar el constructor de Fraccion:
public class Fraccion
{
. . .
public Fraccion(int numerador, int denominador)
throws DenominadorNulException
{
if (denominador == 0)
{
throw new DenominadorNulException();
}
this.numerador = numerador;
this.denominador = denominador;
}
. . .
}
Cuando el denominador vale 0, el constructor lanza una excepción:
throw new DenominadorNulException();
El constructor decide remontar este error al programa llamador:
throws DenominadorNulException...
Trabajo práctico: introducir valores enteros
1. Tema
El método readInt() de la clase Teclado (paquete herramientasMG.varios) genera dos tipos de excepciones:
-
Una excepción monitorizada IOException.
-
Una excepción no monitorizada NumberFormatException, que se produce en caso de introducir datos incorrectos.
Trabajo para realizar:
-
Escribir una clase TecladoInt con un método readInt(int min, int max). Este método devuelve, además de los dos errores anteriores, un error de tipo LimiteExcepcion si el valor introducido no está incluido entre los límites min y max.
-
Escribir una clase ControlInt, con un método rellenaInt(int min, int max) que permite introducir el valor de un entero en bucle hasta que el valor introducido sea correcto.
Programa de comprobación de ControlInt:
import java.io.*;
public class VerificaControlInt
{
public static void main(String argv[]) throws IOException
{
int i;
i = ControlInt.rellenaInt(150, 200);
System.out.println("Valor introducido: " + i);
}
}
A continuación se muestra un ejemplo de resultado de la ejecución de este programa:
2. Introducir enteros: propuesta de corrección
a. Clase LimiteExcepcion
La clase LimiteExcepcion hereda de Exception. Es una excepción monitorizada.
El constructor de LimiteExcepcion llama al de Exception, enviándole una cadena formada a partir de tres argumentos:
-
valor: entero en error;
-
min: límite inferior;
-
max: límite superior.
El mensaje formado de esta manera es accesible por el método...