Pueden mencionarse esencialmente tres ventajas principales en el uso de excepciones (vea Advantages of Exceptions):
- Separación del código "regular" del de manejo de errores.
- Propagación de errores hacia la pila de métodos.
- Agrupación y diferenciación de tipos de errores.
Separación del código "regular" del de manejo de errores.
Las excepciones proporcionan un mecanismo para separar los detalles de la lógica principal del programa, respecto a lo que hay que hacer cuando ocurre algo fuera de lo ordinario.
Considere el siguiente pseudocódigo para leer un archivo completo en la memoria:
Las excepciones proporcionan un mecanismo para separar los detalles de la lógica principal del programa, respecto a lo que hay que hacer cuando ocurre algo fuera de lo ordinario.
Considere el siguiente pseudocódigo para leer un archivo completo en la memoria:
readFile {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
}
El flujo principal parece bastante simple pero (las cosas a veces salen mal):
- ¿Qué pasa si el archivo no se puede abrir?
- ¿Qué pasa si su longitud no puede ser determinada?
- ¿Qué pasa si no se puede obtener memoria suficiente para contenerlo?
- ¿Qué pasa si falla su lectura?
- ¿Qué pasa si el archivo no se puede cerrar?
errorCodeType readFile {
initialize errorCode = 0;
open the file;
if (theFileIsOpen) {
determine the length of the file;
if (gotTheFileLength) {
allocate that much memory;
if (gotEnoughMemory) {
read the file into memory;
if (readFailed){
errorCode = -1;
}
} else
errorCode = -2;
} else
errorCode = -3;
close the file;
if (theFileDidntClose && errorCode == 0)
errorCode = -4;
else
errorCode = errorCode and -4;
else
errorCode = -5;
return errorCode;
}
Las excepciones no ahorran el trabajo del manejo de errores, pero permiten mantener el flujo principal del programa limpio y realizar dicho manejo de errores en otra parte:
readFile {
try {
open the file;
determine its size;
allocate that much memory;
read the file into memory;
close the file;
} catch (fileOpenFailed) {
doSomething;
} catch (sizeDeterminationFailed) {
doSomething;
} catch (memoryAllocationFailed) {
doSomething;
} catch (readFailed) {
doSomething;
} catch (fileCloseFailed) {
doSomething;
}
}
Propagación de errores hacia la pila de métodos.
La segunda ventaja es la capacidad de propagar un error. Considere lo siguiente y suponga que method1 es el único interesado en los errores que pudieran ocurrir dentro de readFile:
method1 {
call method2;
}
method2 {
call method3;
}
method3 {
call readFile;
}
Para la detección y manejo correspondiente utilizando técnicas tradicionales:
method1 {
errorCodeType error;
error = call method2;
if (error)
doErrorProcessing;
else
proceed;
}
errorCodeType method2 {
errorCodeType error;
error = call method3;
if (error)
return error;
else
proceed;
}
errorCodeType method3 {
errorCodeType error;
error = call readFile;
if (error)
return error;
else
proceed;
}
Por el mecanismo que tiene la máquina virtual de Java de buscar en la pila de métodos uno que esté interesado en realizar el manejo de una excepción en particular, sólo los métodos interesados se preocupan del manejo de errores:
method1 {
try {
call method2;
} catch (exception e) {
doErrorProcessing;
}
}
method2 throws exception {
call method3;
}
method3 throws exception {
call readFile;
}
Agrupación y diferenciación de tipos de errores.
Debido a que todas las excepciones lanzadas por un programa son objetos, la agrupación y caracterización en categorías de excepciones es un resultado natural de la jerarquía de clases.
Un método puede considerar un manejador específico para una excepción determinada:
Un método puede considerar un manejador específico para una excepción determinada:
catch (FileNotFoundException e) {
...
}
o bien puede atrapar una excepción basándose en su grupo o tipo general es decir, alguna de sus super clases en la línea de generalización / herencia:
catch (IOException e) {
...
}
en este sentido, se pueden encontrar los detalles particulares de lo que ocurrió a través de una consulta al argumento enviado al manejador de excepción:
catch (IOException e) {
// Output goes to System.err.
e.printStackTrace();
// Send trace to stdout.
e.printStackTrace(System.out);
}
incluso se puede hacer un manejador de excepciones que gestione cualquier excepción:
// A (too) general exception handler
catch (Exception e) {
...
}
En resumen, se pueden crear grupos de excepciones y darles un manejo general, o se pueden utilizar categorías especificas de excepciones para diferenciarlas y manejarlas de una manera más precisa.