2012-06-09 27 views
27

Si no me equivoco, las subclases de Excepciones deben detectarse primero. Pero tener que atrapar cualquier RuntimeException y una Excepción verificada concreta, que debería ser capturada al principio?Orden de captura de excepciones en Java

try { 
    ... 
} catch(RuntimeException e) { 
    ... 
} catch(IOException e) { 
    ... 
} 

¿Es esta orden correcta? ¿O es correcto, pero es una mala opción?

Respuesta

49

El orden es lo que coincida primero, se ejecuta (as the JLS clearly explains).

Si la primera coincidencia coincide con la excepción, se ejecuta, si no lo hace, se prueba la siguiente y así sucesivamente hasta que uno coincida o ninguno.

Por lo tanto, cuando capture excepciones, siempre deberá detectar el más específico y luego el más genérico (como RuntimeException o Exception). Por ejemplo, imagine que desea coger el StringIndexOutOfBoundsException arrojados por el método String.charAt(index) pero su código también podría lanzar un NullPointerException, aquí es cómo usted podría ir a coger las excepciones:

String s = null; 
try { 
    s.charAt(10); 
} catch (NullPointerExeption e) { 
    System.out.println("null"); 
    e.printStackTrace(); 
} catch (StringIndexOutOfBoundsException e) { 
    System.out.println("String index error!"); 
    e.printStackTrace(); 
} catch (RuntimeException e) { 
    System.out.println("runtime exception!"); 
    e.printStackTrace(); 
} 

Así, con este fin, Me aseguro de que las excepciones se capten correctamente y no se tropiecen entre sí, si es NullPointerException ingresa el primer catch, si StringIndexOutOfBoundsException ingresa el segundo y finalmente si es otra cosa que es RuntimeException (o hereda de él, como un IllegalArgumentException) entra en la tercera captura.

Su caso es correcto ya que IOException hereda de Exception y RuntimeException también hereda de Exception, por lo que no se tropezarán entre sí.

Es también un error de compilación para atrapar una excepción genérica primero y luego uno de los descendientes es tarde, como en:

try { 
    // some code here 
} catch (Exception e) { 
    e.printStackTrace(); 
} catch (RuntimeException e) { // this line will cause a compilation error because it would never be executed since the first catch would pick the exception 
    e.printStackTrace(); 
} 

Por lo tanto, usted debe tener los niños en primer lugar y luego las excepciones de los padres.

+0

'Quiero' no tiene nada que ver con eso. El compilador impone el orden correcto. – EJP

1

Cualquier orden que el compilador acepte es correcta.

+0

@downvoter Explicación por favor. No hay error aquí Ambas otras respuestas están de acuerdo. Si no está de acuerdo, hágalo explícitamente, pero prepárese para citar el capítulo y el versículo. – EJP

4

¿Es esta orden correcta? ¿O es correcto, pero es una mala opción?

Ninguno. Como han dicho otras respuestas, el compilador debería decirle si coloca capturas simples en un orden donde una enmascara otra.

Pero hay otro problema potencial en su código: ¿debería realmente capturar RuntimeException en absoluto. El problema es que hay muchas fuentes/causas de excepciones desactivadas, y muchas de esas fuentes/causas son en realidad errores en su aplicación.

Utilizando el catch registrar un diagnóstico como parte de una parada de emergencia está bien, pero si se captura e intenta recuperarse deRuntimeException, es necesario tener cuidado de que no está barriendo un serio problema debajo de la alfombra :

  • Asegúrese de que se conecte la excepción y su StackTrace, no importa qué.

  • Considere si es sabio para tratar de recuperar. Si tienes un error desconocido, podría haber causado daños impredecibles antes de activar la excepción. No tiene forma de saber si la aplicación se puede recuperar o si podría causar un daño mayor al intentar continuar.

El mismo consejo se aplica a la captura de Exception y Throwable/Error. Y es más crítico con Throwable/Error debido a la naturaleza del daño que bien podría haber ocurrido.

+0

Ese es un buen punto. ¿Pero a qué te refieres con decir "e intentar recuperar de RuntimeException"? No intenté hacer eso, en realidad uno no necesita recuperarse de RuntimeException. ¿O uno? –

+0

Por "intento de recuperación" me refiero a hacer algo más que permitir o hacer que la aplicación salga. No está claro si su código hace eso o no. (Depende de lo que ocurra en el código adjunto.) De todos modos, no estoy diciendo que * hagas * esto. Más bien, estoy ofreciendo consejos generales que se aplican siempre que su código capte una de las clases de excepción raíz. –

+0

Oh, ya veo, gracias. –

Cuestiones relacionadas