Manejo de Errores Usando Excepciones Java

El t�rmino excepci�n es un forma corta da la frase "suceso excepcional" y puede definirse de la siguiente forma.

Definici�n:

Una excepci�n es un evento que ocurre durante la ejecuci�n del programa que interrumpe el flujo normal de las sentencias.

Muchas clases de errores pueden utilizar excepciones -- desde serios problemas de hardware, como la aver�a de un disco duro, a los simples errores de programaci�n, como tratar de acceder a un elemento de un array fuera de sus l�mites. Cuando dicho error ocurre dentro de un m�todo Java, el m�todo crea un objeto 'exception' y lo maneja fuera, en el sistema de ejecuci�n. Este objeto contiene informaci�n sobre la excepci�n, incluyendo su tipo y el estado del programa cuando ocurri� el error. El sistema de ejecuci�n es el responsable de buscar alg�n c�digo para manejar el error. En terminolog�a java, crear una objeto exception y manejarlo por el sistema de ejecuci�n se llama lanzar una excepci�n.

Despu�s de que un m�todo lance una excepci�n, el sistema de ejecuci�n entra en acci�n para buscar el manejador de la excepci�n. El conjunto de "algunos" m�todos posibles para manejar la excepci�n es el conjunto de m�todos de la pila de llamadas del m�todo donde ocurri� el error. El sistema de ejecuci�n busca hacia atr�s en la pila de llamadas, empezando por el m�todo en el que ocurri� el error, hasta que encuentra un m�todo que contiene el "manejador de excepci�n" adecuado.

Un manejador de excepci�n es considerado adecuado si el tipo de la excepci�n lanzada es el mismo que el de la excepci�n manejada por el manejador. As� la excepci�n sube sobre la pila de llamadas hasta que encuentra el manejador apropiado y una de las llamadas a m�todos maneja la excepci�n, se dice que el manejador de excepci�n elegido captura la excepci�n.

Si el sistema de ejecuci�n busca exhaustivamente por todos los m�todos de la pila de llamadas sin encontrar el manejador de excepci�n adecuado, el sistema de ejecuci�n finaliza (y consecuentemente y el programa Java tambi�n).

Mediante el uso de excepciones para manejar errores, los programas Java tienen las siguientes ventajas frente a las t�cnicas de manejo de errores tradicionales.

.�Ventaja 1: Separar el Manejo de Errores del C�digo "Normal"

En la programaci�n tradicional, la detecci�n, el informe y el manejo de errores se convierte en un c�digo muy liado. Por ejemplo, supongamos que tenemos una funci�n que lee un fichero completo dentro de la memeoria. En pseudo-c�digo, la funci�n se podr�a parecer a esto.

leerFichero {
    abrir el fichero;
    determinar su tama�o;
    asignar suficiente memoria;
    leer el fichero a la memoria;
    cerrar el fichero;
}

A primera vista esta funci�n parece bastante sencilla, pero ignora todos aquello errores potenciales.

  • �Qu� sucede si no se puede abrir el fichero?
  • �Qu� sucede si no se puede determinar la longitud del fichero?
  • �Qu� sucede si no hay suficiente memoria libre?
  • �Qu� sucede si la lectura falla?
  • �Qu� sucede si no se puede cerrar el fichero?

Para responder a estas cuestiones dentro de la funci�n, tendr�amos que a�adir mucho c�digo para la detecci�n y el manejo de errores. El aspecto final de la funci�n se parecer�a esto.

codigodeError leerFichero {
    inicializar codigodeError = 0;
    abrir el fichero;
    if (ficheroAbierto) {
        determinar la longitud del fichero;
        if (obtenerLongitudDelFichero) {
            asignar suficiente memoria;
            if (obtenerSuficienteMemoria) {
                leer el fichero a memoria;
                if (falloDeLectura) {
                    codigodeError = -1;
                }
            } else {
                codigodeError = -2;
            }
        } else {
            codigodeError = -3;
        }
        cerrar el fichero;
        if (ficheroNoCerrado && codigodeError == 0) {
            codigodeError = -4;
        } else {
            codigodeError = codigodeError and -4;
        }
    } else {
        codigodeError = -5;
    }
    return codigodeError;
}

Con la detecci�n de errores, las 7 l�neas originales (en negrita) se han covertido en 29 l�neas de c�digo-- a aumentado casi un 400 %. Lo peor, existe tanta detecci�n y manejo de errores y de retorno que en las 7 l�neas originales y el c�digo est� totalmente atestado. Y a�n peor, el flujo l�gico del c�digo tambi�n se pierde, haciendo d�ficil poder decir si el c�digo hace lo correcto (si �se cierra el fichero realmente si falla la asignaci�n de memoria?) e incluso es d�ficil asegurar que el c�digo continue haciendo las cosas correctas cuando se modifique la funci�n tres meses despu�s de haberla escrito. Muchos programadores "resuelven" este problema ignor�dolo-- se informa de los errores cuando el programa no funciona.

Java proporciona una soluci�n elegante al problema del tratamiento de errores: las excepciones. Las excepciones le permiten escribir el flujo principal de su c�digo y tratar los casos excepcionales en otro lugar. Si la funci�n leerFcihero utilizara excepciones en lugar de las t�cnicas de manejo de errores tradicionales se podr�a parecer a esto.

leerFichero {
    try {
           abrir el fichero;
           determinar su tama�o;
           asignar suficiente memoria;
           leer el fichero a la memoria;
           cerrar el fichero;
    } catch (falloAbrirFichero) {
        hacerAlgo;
    } catch (falloDeterminacionTama�o) {
        hacerAlgo;
    } catch (falloAsignaciondeMemoria) {
        hacerAlgo;
    } catch (falloLectura) {
        hacerAlgo;
    } catch (falloCerrarFichero) {
        hacerAlgo;
    }
}

Observa que las excepciones no evitan el esfuerzo de hacer el trabajo de detectar, informar y manejar errores. Lo que proporcionan las excepciones es la posibilidad de separar los detalles oscuros de qu� hacer cuando ocurre algo fuera de la normal.

Adem�s, el factor de aumento de c�odigo de este es programa es de un 250% -- comparado con el 400% del ejemplo anterior.

.�Ventaja 2: Propagar los Errores sobre la Pila de Llamadas

Una segunda ventaja de las exepciones es la posibilidad del propagar el error encontrado sobre la pila de llamadas a m�todos. Supongamos que el m�todo leerFichero es el cuarto m�todo en una serie de llamadas a m�todos anidadas realizadas por un programa principal: metodo1 llama a metodo2, que llama a metodo3, que finalmente llama a leerFichero.

metodo1 {
    call metodo2;
}
metodo2 {
    call metodo3;
}
metodo3 {
    call leerFichero;
}

Supongamos tambi�n que metodo1 es el �nico m�todo interesado en el error que ocurre dentro de leerFichero. Tradicionalmente las t�cnicas de notificaci�n del error forzar�an a metodo2 y metodo3 a propagar el c�digo de error devuelto por leerFichero sobre la pila de llamadas hasta que el c�digo de error llegue finalmente a metodo1 -- el �nico m�todo que est� interesado en �l.

metodo1 {
    codigodeErrorType error;
    error = call metodo2;
    if (error)
        procesodelError;
    else
        proceder;
}
codigodeErrorType metodo2 {
    codigodeErrorType error;
    error = call metodo3;
    if (error)
        return error;
    else
        proceder;
}
codigodeErrorType metodo3 {
    codigodeErrorType error;
    error = call leerFichero;
    if (error)
        return error;
    else
        proceder;
}

Como se aprendi� anteriormente, el sistema de ejecuci�n Java busca hacia atr�s en la pila de llamadas para encontrar cualquier m�todo que est� interesado en manejar una excepci�n particular. Un m�todo Java puede "esquivar" cualquier excepci�n lanzada dentro de �l, por lo tanto permite a los m�todos que est�n por encima de �l en la pila de llamadas poder capturarlo. S�lo los m�todos interesados en el error deben preocuparse de detectarlo.

metodo1 {
    try {
        call metodo2;
    } catch (excepcion) {
        procesodelError;
    }
}
metodo2 throws excepcion {
    call metodo3;
}
metodo3 throws excepcion {
    call leerFichero;
}

Sin embargo, como se puede ver desde este pseudo-c�digo, requiere cierto esfuerzo por parte de los m�todos centrales. Cualquier excepci�n chequeada que pueda ser lanzada dentro de un m�todo forma parte del interface de programaci�n p�blico del m�todo y debe ser especificado en la clausula throws del m�todo. As� el m�todo informa a su llamador sobre las excepciones que puede lanzar, para que el llamador pueda decidir concienzuda e inteligentemente qu� hacer con esa excepci�n.

Observa de nuevo la diferencia del factor de aumento de c�digo y el factor de ofuscaci�n entre las dos t�cnicas de manejo de errores. El c�digo que utiliza excepciones es m�s compacto y m�s f�cil de entender.

.�Ventaja 3: Agrupar Errores y Diferenciaci�n

Frecuentemente las excepciones se dividen en categorias o grupos. Por ejemplo, podr�amos imaginar un grupo de excepciones, cada una de las cuales representara un tipo de error espec�fico que pudiera ocurrir durante la manipulaci�n de un array: el �ndice est� fuera del rango del tama�o del array, el elemento que se quiere insertar en el array no es del tipo correcto, o el elemento que se est� buscando no est� en el array. Adem�s, podemos imaginar que algunos m�todos querr�an manejar todas las excepciones de esa categoria (todas las excepciones de array), y otros m�todos podr�a manejar s�lo algunas excepciones espec�ficas (como la excepci�n de �ndice no v�lido).

Como todas las excepciones lanzadas dentro de los programas Java son objetos de primera clase, agrupar o categorizar las excepciones es una salida natural de las clases y las superclases. Las excepciones Java deben ser ejemplares de la clase Throwable, o de cualquier descendiente de �sta. Como de las otras clases Java, se pueden crear subclases de la clase Throwable y subclases de estas subclases. Cada clase 'hoja' (una clase sin subclases) representa un tipo espec�fico de excepci�n y cada clase 'nodo' (una clase con una o m�s subclases) representa un grupo de excepciones relacionadas.

InvalidIndexException, ElementTypeException, y NoSuchElementException son todas clases hojas. Cada una representa un tipo espec�fico de error que puede ocurrir cuando se manipula un array. Un m�todo puede capturar una excepci�n basada en su tipo espec�fico (su clase inmediata o interface). Por ejemplo, una manejador de excepci�n que s�lo controle la excepci�n de �ndice no v�lido, tiene una sentencia catch como esta.

catch (InvalidIndexException e) {
    . . .
}

ArrayException es una clase nodo y representa cualquier error que pueda ocurrir durante la manipulaci�n de un objeto array, incluyendo aquellos errores representados espec�ficamente por una de sus subclases. Un m�todo puede capturar una excepci�n basada en este grupo o tipo general especificando cualquiera de las superclases de la excepci�n en la sentencia catch. Por ejemplo, para capturar todas las excepciones de array, sin importar sus tipos espec�ficos, un manejador de excepci�n especificar�a un argumento ArrayException.

catch (ArrayException e) {
    . . .
}

Este manejador podr�a capturar todas las excepciones de array, incluyendo InvalidIndexException, ElementTypeException, y NoSuchElementException. Se puede descubrir el tipo de excepci�n preciso que ha ocurrido comprobando el par�mtero del manejador e. Incluso podr�amos seleccionar un manejador de excepciones que controlara cualquier excepci�n con este manejador.

catch (Exception e) {
    . . .
}

Los manejadores de excepciones que son demasiado generales, como el mostrado aqu�, pueden hacer que el c�digo sea propenso a errores mediante la captura y manejo de excepciones que no se hubieran anticipado y por lo tanto no son manejadas correctamente dentro de manejador. Como regla no se recomienda escribir manejadores de excepciones generales.

Como has visto, se pueden crear grupos de excepciones y manejarlas de una forma general, o se puede especificar un tipo de excepci�n espec�fico para diferenciar excepciones y manejarlas de un modo exacto.

.�� Y ahora qu�?

Ahora que has entendido qu� son las excepciones y las ventajas de su utilizanci�n en los programas Java, es hora de aprender c�mo utilizarlas.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP
ARTÍCULO ANTERIOR

SIGUIENTE ARTÍCULO