2012-07-02 25 views
16

A veces, voy a terminar encima de tener que capturar una excepción, que yo sepa nunca puede pasar, como aquí¿Cómo se manejan las excepciones "imposibles" en Java?

URLDecoder.decode("some string", "UTF-8"); //No unknown encoding possible 

o aquí:

public void methodWithURL(URL url){ 
    URI uri = new URI(url); //No invalud URI syntax possible 
} 

¿cómo manejar esto? En general, registro un error gracioso con respecto a cómo han cambiado las leyes del universo, y luego lanzo un RuntimeException. ¿Hay una mejor manera?

+3

try/catch (XXXException _ex) {throw new AssertionError (_ex);} – bestsss

+0

@bestsss También he oído hablar de AssertionError como alternativa a RuntimeException. ¿Es esa la manera general de hacer esto sobre RuntimeException, o simplemente una mejor forma de subclasificar este tipo de errores? ¡Gracias! (también, es posible que desee escribir en la sección de respuestas) – Miquel

+1

El error no amplía Exception, por lo que omite el 'try/catch (Exception any) usado en exceso '. Cualquier cosa que atrape 'Throwable' tratará w /' Error' explícitamente. El código del cliente no detectará 'Error' sin razón alguna. La única excepción de inicio de sesión que * no ocurrirá * generalmente no es lo correcto. Y, no, no quiero probar una respuesta :) – bestsss

Respuesta

9

Cojo el Exception y lo envuelvo en un Error. Del documento de Error:

Un error es una subclase de Throwable que indica problemas serios que una aplicación razonable no debe tratar de atrapar.

+0

Muchas gracias Julien. Ahora estoy bastante convencido de que arrojar un derivado de 'Error' es la mejor manera. @bestsss también hizo algunas sugerencias en la sección de comentarios de la pregunta, incluido el uso de AssertionError – Miquel

+0

+1. Ahora _este_ es una respuesta realmente sólida. No es específico como 'AssertionError' (que puede parecer extraño en ausencia de una declaración' assert') y tiene el mismo efecto que 'RuntimeException'. Además, indica un problema con el "sistema" en lugar de la lógica del código. Me gusta. Me pregunto si este enfoque es ampliamente conocido o no, o si hay algún inconveniente. –

+1

* Además, indica un problema con el "sistema" * Eso es 'InternalError' para. Solía ​​usarlo en 1.1 pero cambié a 'AssetionError' en 1.4 (también ofrece un c-tor w/Throwable). Además, algunos errores pueden no ser el resultado exacto de un error del sistema, sino de la programación de los datos o de las carreras de datos. Por cierto, pocos lugares en Java usan 'System.exit (-1)' – bestsss

3

Bueno, en mi humilde opinión es una mejor manera que "registrar [ging] un error gracioso con respecto a cómo las leyes del universo han cambiado" porque al hacerlo estás "siendo lindo", que entre amigos está bien, pero no es universal (sin juego de palabras) aceptado. Su código puede ser leído por otros y si su humor no es claro (en ellos) realmente no ha hecho ningún amigo.

Muchas guías de estilo hacen sugerencias para excepciones imposibles. Puede usar un bloque de catch vacío con el parámetro de excepción llamado willNeverHappen; puedes colocar un comentario en el bloque vacío; usted puede lanzar una excepción de tiempo de ejecución (probablemente la mejor, ya que FUERZA misspell UTF-8!)

Si quieres ser súper ambiciosa, puede escribir una anotación, como SneakyThrows in Lombok. Si lo considerarías "mejor" es simplemente una cuestión de gusto. :)

Tenga en cuenta que esta pregunta se discutió en https://softwareengineering.stackexchange.com/questions/122233/how-to-deal-with-checked-exceptions-that-cannot-ever-be-thrown.

+0

Gracias por su respuesta Ray; No estoy seguro de que recomiende bloques de captura vacíos (comentario o no), pero usted tiene el argumento de que las opciones imposibles * podrían * ser posibles algún día. En cuanto al humor, estoy seguro de que hay muchas opiniones (¿tal vez depende de la cultura de la empresa?), Pero tienes razón en que nadie debería sufrir un error durante horas, solo para encontrarlo causado por una excepción mal manejada y un mensaje divertido. – Miquel

+0

Odio el bloque de catch vacío también: "comer" excepciones es una práctica horrible. Y sí, traté de decir que el humor estaba bien en algunos círculos; solo conlleva el riesgo de que un futuro lector del código no lo entienda, por lo que dicho enfoque debe considerarse cuidadosamente. Si se elige, lo mejor es hacerlo algo que todos los lectores comprenderán y no algo que dependa de una cultura pop o una referencia a algo esotérico. Una "violación de las leyes del universo" probablemente está bien. Dicho esto, 'RuntimeException' o su primo' Error' son la mejor opción. –

5

Me saltaría el mensaje gracioso.

BTW: Tuve un caso en el que un fragmento de código (en una pequeña biblioteca) simplemente suponía que una codificación estaría disponible. Solo se desplegó en un dispositivo limitado y explotó en tiempo de ejecución.

Las excepciones comprobadas sirven para mostrar lugares en nuestro código donde deberíamos detenernos un momento y considerar las rutas menos transitadas (como en "lo que hace mi aplicación cuando la red muere" y otros casos de esquina). Envolverlos en IllegalStateException y reingresar es una especie de contrato firmado, donde el programador dice: "sí, todos los riesgos considerados, yo asumo la plena responsabilidad del lugar justo aquí". Si no fuera por las excepciones marcadas, no tendríamos forma de saber una decisión conciente de una simple falta de pensamiento.

+0

Muchas gracias por su ejemplo para hacer posible lo imposible. Esto es exactamente lo que temía, y es por eso que quería consultar con ustedes. Además, no estaba despotricando contra las excepciones comprobadas, las considero una parte fundamental de Java, pero me preguntaba cómo manejar las imposibles (¿realmente poco probables?) – Miquel

0

aquí está mi solución - desarrollado para Android, pero puede adaptarse fácilmente para Java "regular":

public class ImpossibleException extends RuntimeException { 
    public ImpossibleException(@NonNull String whyNotPossible) { 
     this(whyNotPossible, null); 
    } 

    public ImpossibleException(@NonNull String whyNotPossible, Throwable throwable) { 
     super("Impossible exception: " + whyNotPossible, throwable); 
     Log.e("Impossible", whyNotPossible, throwable); 
    } 
} 

Uso:

try { 
    byte[] data = "Hello".getBytes("utf-8"); 
    Log.i("Test", "data.length=" + data.length); 
} catch (UnsupportedEncodingException e) { 
    throw new ImpossibleException("Android always supports utf-8", e); 
} 

significa El constructor whyNotPossible no hay necesidad de registrar el error donde sucede, y tampoco hay necesidad de un comentario.

Supongo que es una cuestión de gusto si esto debería ser un ImpossibleException extends RuntimeException o un ImpossibleError extends Error.

Cuestiones relacionadas