Primer Encuentro con las Excepciones Java

InputFile.java:8: Warning: Exception java.io.FileNotFoundException 
must be caught, or it must be declared in throws clause of this method.
        fis = new FileInputStream(filename);
              ^
El mensaje de error anterior es uno de los dos mensajes similares que verás si intentas compilar la clase InputFile, porque la clase InputFile contiene llamadas a métodos que lanzan excepciones cuando se produce un error. El lenguaje Java requiere que los métodos capturen o especifiquen todas las excepciones chequeadas que puedan ser lanzadas desde dentro del ámbito de ese método. (Los detalles sobre lo que ocurre los puedes ver en la próxima página Requerimientos de Java para Capturar o Especificar.)

Si el compilador detecta un método, como los de InputFile, que no cumplen este requerimiento, muestra un error como el anterior y no compila el programa.

Echemos un vistazo a InputFile en más detalle y veamos que sucede.

La clase InputFile envuelve un canal FileInputStream y proporciona un método, getLine(), para leer una línea en la posición actual del canal de entrada.

    // Nota: Esta clase no se compila por diseño!
import java.io.*;

class InputFile {

    FileInputStream fis;

    InputFile(String filename) {
        fis = new FileInputStream(filename);
    }

    String getLine() {
        int c;
        StringBuffer buf = new StringBuffer();

        do {
            c = fis.read();
            if (c == '\n')             // nueva línea en UNIX
                return buf.toString();
            else if (c == '\r') {      // nueva línea en Windows 95/NT 
                c = fis.read();
                if (c == '\n')
                    return buf.toString();
                else {
                    buf.append((char)'\r');
                    buf.append((char)c);
                }
            } else
                buf.append((char)c);
        } while (c != -1);

        return null;
    }
}
El compilador dará el primer error en la primera línea que está en negrita. Esta línea crea un objeto FileInputStream y lo utiliza para abrir un fichero (cuyo nombre se pasa dentro del constructor del FileInputStream).

Entonces, ¿Qué debe hacer el FileInputStream si el fichero no existe? Bien, eso depende de lo que quiera hacer el programa que utiliza el FileInputStream. Los implementadores de FileInputStream no tenian ni idea de lo que quiere hacer la clase InputFile si no existe el fichero. ¿Debe FileInputStream terminar el programa? ¿Debe intentar un nombre alternativo? o ¿deberóa crear un fichero con el nombre indicado? No existe un forma posible de que los implemetadores de FileInputStream pudieran elegir una solución que sirviera para todos los usuarios de FileInputStream. Por eso ellos lanzaron una excepción. Esto es, si el fichero nombrado en el argumento del constructor de FileInputStream no existe, el constructor lanza una excepción java.io.FileNotFoundException. Mediante el lanzamiento de esta excepción, FileInputStream permite que el método llamador maneje ese error de la forma que considere más apropiada.

Como puedes ver en el listado, la clase InputFile ignora completamente el hecho de que el constructor de FileInputStream puede lanzar un excepción. Sin embargo, El lenguaje Java requiere que un método o bien lance o especifique todas las excepciones chequeadas que pueden ser lanzadas desde dentro de su ámbito. Como la Clase InputFile no hace ninguna de las dos cosas, el compilador rehusa su compilación e imprime el mensaje de error.

Además del primer error mostrado arriba, se podrá ver el siguiente mensaje de error cuando se compile la clase InputFile:

InputFile.java:15: Warning: Exception java.io.IOException must be caught, 
or it must be declared in throws clause of this method.
        while ((c = fis.read()) != -1) {
                            ^
El método getLine() de la clase InputFile lee una línea desde el FileInputStream que fue abierto por el constructor de InputFile. El método read() de FileInputStream lanza la excepción java.io.IOException si por alguna razón no pudiera leer el fichero. De nuevo, la clase InputFile no hace ningún intento por capturar o especificar esta excepción lo que se convierte en el segundo mensaje de error.

En este punto, tenemos dos opciones. Se puede capturar las excepciones con los métodos apropiados en la clase InputFile, o se puede esquivarlas y permitir que otros métodos anteriores en la pila de llamadas las capturen. De cualquier forma, los métodos de InputFile deben hacer algo, o capturar o especificar las excepciones, antes de poder compilar la clase InputFile. Aquí tiene la clase InputFileDeclared, que corriege los errores de InputFile mediante la especificación de las excepciones.

La siguiente página le describe con más detalles los Requerimientos de Java para Capturar o Especificar. Las páginas siguientes le enseñarán cómo cumplir estos requerimientos.


Ozito