practice - ¿Debería la clase IOException en Java haber sido una RuntimeException no revisada?
java exception hierarchy (6)
¿Está de acuerdo en que los diseñadores de Java clase java.io.IOException
deberían haberlo convertido en una excepción de tiempo de ejecución no comprobada derivada de java.lang.RuntimeException
lugar de una excepción comprobada derivada solo de java.lang.Exception
?
Creo que la clase IOException
debería haber sido una excepción no comprobada porque es poco lo que una aplicación puede hacer para resolver problemas como los errores del sistema de archivos. Sin embargo, en Cuando no se puede lanzar una excepción , Elliotte Rusty Harold afirma que la mayoría de los errores de E / S son transitorios, por lo que puede volver a intentar una operación de E / S varias veces antes de abandonar:
Por ejemplo, un IOComparator podría no tener un error de E / S acostado, pero debido a que muchos problemas de E / S son transitorios, puede volver a intentarlo varias veces, como se muestra en el Listado 7:
Es este generalmente el caso? ¿Puede una aplicación Java corregir errores de E / S o esperar a que el sistema se recupere? Si es así, entonces es razonable que se compruebe IOException, pero si no es el caso, entonces IOException se debe desmarcar para que la lógica empresarial pueda delegar el manejo de esta excepción a un manejador de errores del sistema por separado.
Creo que es inteligente dejarlo como una excepción marcada. Considero las excepciones de tiempo de ejecución como errores , y claramente este no es el caso. La recuperación por reintento a veces es posible, y también algunos mensajes IOException pueden ser informativos para el usuario final (por ejemplo, no hay permisos para escribir, no hay suficiente espacio en disco, etc.).
No porque puede recuperarse de algunas IOExcepciones. Los más notables son las lecturas y escrituras indexadas de bajo nivel. Si falla, a veces puedes volver a intentarlo sin daño.
Probablemente la gran mayoría de las excepciones de IO son recuperables: errores de permisos, falta de espacio en el disco, conexión cerrada, etc., etc. Creo que se deben usar excepciones no comprobadas para "no hay forma razonable de recuperarse de este" tipo de situaciones .
En un marco de excepción bien diseñado, debe hacerse una distinción entre las excepciones que, en cierta medida, son "esperadas" y las que no lo son. Java intenta usar excepciones comprobadas versus no marcadas para esto. Según ese estándar, IOException debe ser una excepción marcada.
Un problema fundamental, sin embargo, es que muchas veces el código se escribirá con una expectativa (quizás razonable) de que no se producirá una determinada excepción, y no se puede hacer nada para manejarla si lo hace. Si se declara que un método arroja una excepción comprobada en particular, Java permite que la persona que llama ignore la excepción si se declara arrojando esa excepción, pero no hay medios por los cuales un método o bloque de código pueda especificar que ciertas excepciones de los métodos invocados no espera que ocurra . Un antipatrón común es:
try
{
methodThatsDeclaredAsThrowingFooExceptionButWont()
}
catch FooException Ex
{
// Never going to happen
}
La suposición aparente es que, dado que el método no arrojará FooException y la única razón por la cual la trampa está ahí para hacer feliz al compilador, no hay razón para que la catch
haga nada. Insidioso, porque si se FooException
una FooException
, por la razón que sea, pasará desapercibida.
Una alternativa es para un método que llama a methodThatsDeclaredAsThrowingFooExceptionButWont para declararse como throws FooException
o throws Exception
, pero tampoco es realmente apropiado. Si un método que no se espera arroje una FooException
, el estado del sistema puede ser diferente de lo que se esperaría cuando se lanza una FooException
.
Por ejemplo, supongamos que uno intenta cargar un documento, pero la rutina de carga de documentos necesita leer algunas tablas de traducción no documentales que se supone deben almacenarse en una ubicación fija; si ese intento falla, hacer que IOException
distribuya a la persona que llama implicaría que hubo un problema al cargar el documento que se está cargando. Si la rutina del documento de carga no está preparada para manejar sensiblemente la posibilidad de que la rutina load-translation-tables pueda fallar, dicha falla no debería filtrarse de la misma manera que una IOException
que ocurría mientras se cargaba el documento.
El remedio adecuado no sería que IOException
fuera una excepción no verificada, sino que debería haber un medio declarativo por el cual el código pudiera indicar que uno o más tipos de excepciones verificadas no deberían filtrarse fuera de un cierto bloque de los métodos llamados por lo tanto, pero en su lugar debe ser envuelto en algún otro tipo de excepción (por ejemplo, RuntimeException).
Sé que han pasado 4 años desde que se hizo esta pregunta, pero se agregó una excepción UncheckedIOException en Java 8.
Estoy en completo desacuerdo. Para mí, el modelo es correcto. Una RuntimeException es una que típicamente denota un error grave en la lógica de la programación (como ArrayIndexOutOfBounds, NullPointer o IllegalArgument) o algo que el tiempo de ejecución ha determinado que realmente no debería estar sucediendo (como SecurityException).
Por el contrario, IOException y sus derivados son excepciones que podrían ocurrir razonablemente durante la ejecución normal de un programa, y una lógica común dictaría que esos problemas deberían abordarse, o al menos el programador debería saber que pueden ocurrir. Por ejemplo, con Archivos si su registrador de aplicaciones no puede escribir sus datos, sería mejor que se viese obligado a atrapar una IOException potencial y recuperar, o que algo que puede no ser crítico para su aplicación derribaría toda la JVM porque nadie pensó atrapar el Excepción sin marcar (como habrás adivinado, elegiré la anterior).
Creo que hay muchas situaciones en las que una IOException es recuperable o, al menos, el programador debe tener conocimiento explícito del potencial, de modo que si no es recuperable, el sistema podría bloquearse más "suavemente".
Hasta donde piensas si el sistema no se puede recuperar, siempre hay alternativas con una excepción marcada. Siempre puede tener sus métodos para declararlo en sus lanzamientos, lanzar una excepción de tiempo de ejecución propia o bloquear violentamente la JVM:
public void doit() throws IOException {
try{
}catch(IOException e){
// try to recover
...
// can''t recover
throw e;
}
}
public void doit() {
try{
}catch(IOException e){
// try to recover
...
// can''t recover
throw new RuntimeException(e);
}
}
public void doit() {
try{
}catch(IOException e){
// try to recover
...
// OH NO!!!!
System.exit(Constant.UNRECOVERABLE_IO_ERROR);
}
}