La cláusula catch comprueba los argumentos en el mismo orden
en que aparezcan en el programa. Si hay alguno que coincida, se ejecuta el
bloque y sigue el flujo de control por el bloque finally (si
lo hay) y concluye el control de la excepción.
Si ninguna de las cláusulas catch coincide
con la excepción que se ha producido, entonces se ejecutará el código de la
cláusula finally (en caso de que la haya). Lo que ocurre en este
caso, es exactamente lo mismo que si la sentencia que lanza la excepción no se
encontrase encerrada en el bloque try.
El flujo de control abandona este método y retorna
prematuramente al método que lo llamó. Si la llamada estaba dentro del ámbito
de una sentencia try, entonces se vuelve a intentar el control de la
excepción, y así continuamente.
Cuando una excepción no es tratada en la rutina en
donde se produce, lo que sucede es lo siguiente. El sistema Java busca un
bloque try..catch más allá de la llamada, pero dentro del
método que lo trajo aquí. Si la excepción se propaga de todas formas hasta lo
alto de la pila de llamadas sin encontrar un controlador específico para la
excepción, entonces la ejecución se detendrá dando un mensaje. Es decir,
podemos suponer que Java nos está proporcionando un bloque catch por
defecto, que imprime un mensaje de error, indica las últimas entradas en la
pila de llamadas y sale.
No hay ninguna sobrecarga en el sistema por
incorporar sentencias try al código. La sobrecarga se produce cuando
se genera la excepción.
Se ha indicado ya que un método debe capturar las
excepciones que genera, o en todo caso, declararlas como parte de su llamada,
indicando a todo el mundo que es capaz de generar excepciones. Esto debe ser
así para que cualquiera que escriba una llamada a ese método esté avisado de
que le puede llegar una excepción, en lugar del valor de retorno normal. Esto
permite al programador que llama a ese método, elegir entre controlar la
excepción o propagarla hacia arriba en la pila de llamadas. La siguiente línea
de código muestra la forma general en que un método declara excepciones que se
pueden propagar fuera de él, tal como se ha visto a la hora de tratar la
sentenciathrows:
tipo_de_retorno(
parametros ) throws e1,e2,e3 { }
Los nombres e1,e2,... deben ser
nombres de excepciones, es decir, cualquier tipo que sea asignable al tipo
predefinido Throwable. Observar que, como en la llamada al método
se especifica el tipo de retorno, se está especificando el tipo de excepción
que puede generar (en lugar de un objetoException).
He aquí un ejemplo, tomado del sistema Java de
entrada/salida:
byte readByte() throws IOException;
short readShort() throws IOException;
char readChar() throws IOException;
void writeByte( int v ) throws IOException;
void writeShort( int v ) throws IOException;
void writeChar( int v ) throws IOException;
Lo más interesante aquí es que la rutina que lee un char,
puede devolver un char; no el entero que se requiere en C. C necesita que se
devuelva un int, para poder pasar cualquier valor a un char, y además
un valor extra (-1) para indicar que se ha alcanzado el final del fichero.
Algunas de las rutinas Java lanzan una excepción cuando se alcanza el fin del
fichero.
Cuando se crea una nueva excepción, derivando de
una clase Exception ya existente, se puede cambiar el mensaje
que lleva asociado. La cadena de texto puede ser recuperada a través de un
método. Normalmente, el texto del mensaje proporcionará información para
resolver el problema o sugerirá una acción alternativa. Por ejemplo:
class
SinGasolina extends Exception {
SinGasolina( String s ) { // constructor
super( s );
}
....
//
Cuando se use, aparecerá algo como esto
try {
if( j
< 1 )
throw new SinGasolina( "Usando deposito de reserva" );
} catch(
SinGasolina e ) {
System.out.println( o.getMessage() );
}
Esto, en tiempo de ejecución originaría la
siguiente salida por pantalla:
>
Usando deposito de reserva
Otro método que es heredado de la superclase Throwable es printStackTrace().
Invocando a este método sobre una excepción se volcará a pantalla todas las
llamadas hasta el momento en donde se generó la excepción (no donde se maneje
la excepción). Por ejemplo:
//
Capturando una excepción en un método
class
testcap {
static int slice0[] = { 0,1,2,3,4 };
public
static void main( String a[] ) {
try {
uno();
}
catch( Exception e ) {
System.out.println(
"Captura de la excepcion en main()" );
e.printStackTrace();
}
}
static
void uno() {
try {
slice0[-1] = 4;
} catch( NullPointerException e ) {
System.out.println( "Captura
una excepcion diferente" );
}
}
}
Cuando se ejecute ese código, en pantalla
observaremos la siguiente salida:
>
Captura de la excepcion en main()
> java.lang.ArrayIndexOutOfBoundsException: -1
at
testcap.uno(test5p.java:19)
at
testcap.main(test5p.java:9)
Con todo el manejo de excepciones podemos concluir
que se proporciona un método más seguro para el control de errores, además de
representar una excelente herramienta para organizar en sitios concretos todo
el manejo de los errores y, además, que se pueden proporcionar mensajes de
error más decentes al usuario indicando qué es lo que ha fallado y por qué, e
incluso podemos, a veces, recuperar al programa automáticamente de los errores.
La degradación que se produce en la ejecución de programas con manejo de
excepciones está ampliamente compensada por las ventajas que representa en
cuanto a seguridad de funcionamiento de esos mismos programas.
INteresante, pero quedé con los ojos irritados..
ResponderEliminarcual es su nobre amigo(a), gracias por la informacion
ResponderEliminar