2010-05-01 11 views
14

Quiero preguntar por qué no tenemos que agregar el bloque try-catch a un RuntimeException mientras que deberíamos hacer eso con otras excepciones?¿Por qué no tenemos que agregar try-catch a una RuntimeException?

me gustaría decir:

public class Main { 
    public static void main(String[] args) { 
     throw new RuntimeException(); 
    } 
} 

Editar: cuando digo: throw new RuntimeException(); es tan claro que hay una excepción que va a pasar, así que por qué el compilador no prohíbe que?

+6

Tenga en cuenta que 'RuntimeExceptions' generalmente se lanzan cuando se produce un error de programación/lógica de código. La solución generalmente es simplemente arreglar el código. Por lo general, no debes atraparlos. – BalusC

+0

¿De verdad? Creo que una de las mejores prácticas es convertir una excepción marcada a una excepción sin marcar que capturarlas todas en un lugar para mostrarlas al usuario. – vodkhang

+0

@ vodkhang lo que intento decir es por qué el compilador no prohíbe un código cuando está claro que habrá una RuntimeException. –

Respuesta

25

Eso es porque es sin marcar excepción. No necesita ser declarado o atrapado explícitamente. También vea el Sun tutorial on the subject.

Actualización:, en general, sólo se debe lanzar una RuntimeException (preferiblemente uno de sus subclasses que aparece en el javadoc) para indicar que la persona que llama está haciendo mal. Es decir. pasando un argumento null (luego arroje NullPointerException), o un argumento ilegal (luego arroje IllegalArgumentException), o se llama al método en el momento/estado incorrecto (luego arroje IllegalStateException), etcétera. Se supone que la persona que llama debe arreglar su código para evitar eso. P.ej. comprobando de antemano si el argumento no es nulo, o si el argumento está en formato/sintaxis correcta, o asegurando que el método sea llamado en el momento correcto.

Si hay una situación específica que debe arrojar una excepción de tiempo de ejecución y no puede usar una de sus subclases específicas, se supone que debe extenderla y documentarla adecuadamente en el nuevo javadoc de la excepción y en el método de llamada, p.ej ConfigurationException extends RuntimeException para el caso en que el código de llamada no haya configurado la aplicación/API correctamente antes de su uso. Esto debería indicar al usuario final (el otro desarrollador) lo suficiente como para actuar en consecuencia.

En pocas palabras: RuntimeExceptions debe identificar problemas recuperables mediante programación que son causados ​​por fallas en el flujo de código o configuración (léase: fallas del desarrollador). Checked Exceptions debería identificar problemas recuperables por programación que son causados ​​por condiciones inesperadas fuera del control del código (por ejemplo, base de datos inactiva, error de E/S de archivo, entrada de usuario final incorrecta, etc.). Errors debe identificar problemas irrecuperables en el programa (por ejemplo, falta de memoria, excepción dentro de un inicializador, etc.).

+0

pero cuando digo: "throw new RuntimeException();" está tan claro que habrá una excepción, entonces ¿por qué el compilador no lo prohíbe? –

+0

No hay nada moralmente malo con una excepción. Las excepciones no verificadas intencionalmente no se verifican. De ahí el nombre sin marcar. –

+0

@ M.H no, no está claro. Un ejemplo es el método List.add(), una implementación normal de la lista, como el arraylist nunca lanzará una UnsupportedOperationException, por lo que no es necesario que esté en la firma de excepción. El método Collections.asUnmodifyableList() devolverá una lista que arrojará una UnsupportedOperationException en las llamadas a List.add. La implementación de List.add consiste solo en throw new UnsupportedOperationException. Con solo tener un objeto de tipo Lista, no puede ver si se lanzará la excepción y una lista normal nunca debería arrojarla. – josefx

2

RuntimeException, Error y sus subclases no son específicamente comprobadas en tiempo de compilación, no son parte del contrato formal del método.

Consulte el Capítulo 11 en el JLS, Excepciones, en particular 11.2, Comprobación de excepciones en tiempo de compilación.

2

Lets argumentan de esta manera. ¿Qué ocurre si NullPointerException se diseñó para ser una excepción de tiempo de compilación? De haber sido así, el compilador tuvo que verificar estrictamente si una variable es nula o no. No hay forma de que esto pueda hacerse.

public void dummyMethod(Object obj){ 

} 

Aquí no hay forma de que el compilador compruebe si el obj puede ser nulo o no. Sin embargo, tiene que haber algún error/excepción que se debe lanzar cuando tiene un escenario de puntero nulo.

+0

¿Afirma que introduciría alguna restricción fundamental si NullPointerException fuera una excepción marcada? No entiendo el ejemplo que me das? Podría tener mucho sentido que el método acepte obj == null en algunas implementaciones. – aioobe

+0

Solo quería que pensaras en términos de aspecto de diseño. Es perfectamente lógico que haya sido revisado y desmarcado. Ahora, para que el compilador compruebe estas reglas, deberá establecer los 'tipos' de ellas, de las cuales RuntimeException es una y NullPointerException es un tipo de ellas. Y la respuesta a su pregunta es sí, es un problema cuando se realiza una verificación de NPE. El ejemplo que he proporcionado es para decir que el Object obj pasado al método puede ser y no puede ser nulo y que este método no tiene idea al respecto. Un compilador nunca puede verificar tales instancias. – bragboy

1

Porque no está prohibido lanzar excepciones de tiempo de ejecución y no tiene que declarar excepciones de tiempo de ejecución.Su programa es un programa Java válido, por lo que el compilador no tiene motivos para quejarse.

1

Básicamente, una excepción no detectada es simplemente una abreviatura para mostrar un mensaje y terminar la aplicación.

¿Por qué tendrías que hacer eso? En algunos casos, puede detectar que algo salió mal, que algunos archivos no se cargaron, falta una API, algunos datos están dañados por alguna razón, o uno de un millón de otras cosas está mal. Si no lanza una excepción, la aplicación simplemente puede bloquearse en otro punto o, en el peor de los casos, continuar ejecutándose mientras el error aumenta, lo que hace que sea mucho más difícil de depurar.

Es importante entender que uno lanza una excepción porque hay un error, la excepción no es el error, es solo el messenger.

+0

+1 gracias respuesta muy útil –

2

por especificación del lenguaje, excepciones sin marcar son no se controla en tiempo de compilación lo que significa que el compilador no requiere métodos para atrapar o para especificar (con un throws) ellos. Las clases que pertenecen a esta categoría se detallan en la sección 11.2 Compile-Time Checking of Exceptions del JLS:

Las clases sin marcar excepciones son la clase y sus subclases RuntimeException, y la clase y sus subclases Error. Todas las demás clases de excepción son clases de excepción marcadas. La API de Java define una serie de clases de excepción, tanto verificadas como no verificadas. Los programadores pueden declarar clases de excepción adicionales, tanto verificadas como no verificadas. Consulte §11.5 para obtener una descripción de la jerarquía de clases de excepción y algunas de las clases de excepciones definidas por la API Java y la máquina virtual Java.

Por lo tanto, como un RuntimeException en una excepción sin marcar, el compilador no lo fuerza a manejarlo. Si desea forzar a la persona que llama de un fragmento de código a manejar una excepción, use una excepción marcada (las subclases de Exception que no sean RuntimeException son todas clases de excepción comprobadas).

1

La mayoría de las respuestas en este foro han estado hablando de la jerarquía de excepciones y el compilador de Java no las captó, pero trataría de responder esto más desde la perspectiva del diseño y por qué tal vez las cosas fueron diseñadas así.

Básicamente, cuando se llama a una función (o escribir algo de código) una excepción puede ser expulsado de ella basado en tres situaciones diferentes:

  1. Sobre la base de una condición ineludible como falta de disponibilidad de la red o alguna archivo esperado falta en el sistema de archivos.

  2. Sobre la base de una condición evitable pero conocido como Integer.parseInt(String) puede lanzar NumberFormatException si la persona que llama pasa una cadena inconvertibles como "Hello", pero la persona que llama puede garantizar validaciones adecuados en su lugar antes de pasar en cualquier cadena a la función y completamente acabar con la posibilidad de generar la excepción. Un caso de uso común podría ser validar el campo de formulario age en una página web antes de pasarlo a capas más profundas que realizan la conversión.

  3. Una condición desconocido o inesperado En cualquier momento en alguna línea de código puede lanzar una excepción en el código porque había algún error que has hecho y no observó la condición de error hasta que despegó en la producción, por lo general sucede con NullPointer Reference, IndexOutOfBounds etc, que si se observa posiblemente corresponde a la categoría 2.

excepciones de categoría 1 están diseñados generalmente como Checked Exceptions ya que tiene que cumplir la comprobación de las condiciones de error inevitables, y para hacer valer sus retrocesos. Por ejemplo, IOException es una excepción comprobada, porque en caso de que esté abriendo un archivo, puede haber muchas cosas que pueden salir mal (como archivos borrados, permisos, etc.) y la validación previa de todas ellas puede ser muy engorrosa.

Las excepciones del 2do tipo generalmente se modelan como Unchecked Exceptions porque es posible que tenga su validación previa en su lugar y puede ser irritante que se vea obligado a utilizar try y catch para situaciones que ya se han ocupado.

Las excepciones del 3er tipo no necesitan preocuparse en general porque no se puede poner el manejo de errores en todas y cada una de las sentencias del código de la aplicación que pueden surgir inesperadamente. Pero a veces puede colocar un controlador global, en algún lugar en la pila de llamadas desde donde se ejecuta casi todo el código de la aplicación y manejarlo de manera genérica para que su aplicación no se bloquee debido a un error inesperado.

Por ejemplo, si está ejecutando una aplicación web, puede configurar su Servlet Container para enviar un 500 Internal Server Error genérico por cualquier error no controlado en su aplicación. O bien, si está ejecutando una aplicación Java independiente, puede guardar los contenidos de su main method en un bloque try catch para evitar bloqueos de la aplicación.

Cuestiones relacionadas