2011-02-23 24 views
14

The javadoc example¿Cómo uso Throwables.propagateIfInstanceOf() de Google Guava?

try { 
    someMethodThatCouldThrowAnything(); 
    } catch (IKnowWhatToDoWithThisException e) { 
    handle(e); 
    } catch (Throwable t) { 
    Throwables.propagateIfInstanceOf(t, IOException.class); 
    Throwables.propagateIfInstanceOf(t, SQLException.class); 
    throw Throwables.propagate(t); 
    } 

no es muy concreto. ¿Cómo se vería un programa real? Realmente no entiendo el propósito de los métodos Throwables.propagateIfInstanceOf(Throwable, Class), propagate(), propagateIfPossible(). ¿Cuándo los uso?

Respuesta

15

El propósito de estos métodos es proporcionar una forma conveniente de tratar con las excepciones marcadas.

Throwables.propagate() es una abreviatura para el idioma común de la excepción comprobada retrowing envuelta en la casilla no marcada (para evitar declararlo en la cláusula throws del método).

Throwables.propagateIfInstanceOf() se utiliza para retromar excepciones marcadas como si sus tipos están declarados en la cláusula throws del método.

En otras palabras, el código en cuestión

public void doSomething() 
    throws IOException, SQLException { 

    try { 
     someMethodThatCouldThrowAnything(); 
    } catch (IKnowWhatToDoWithThisException e) { 
     handle(e); 
    } catch (Throwable t) { 
     Throwables.propagateIfInstanceOf(t, IOException.class); 
     Throwables.propagateIfInstanceOf(t, SQLException.class); 
     throw Throwables.propagate(t); 
    } 
} 

es una abreviatura para el siguiente código:

public void doSomething() 
    throws IOException, SQLException { 

    try { 
     someMethodThatCouldThrowAnything(); 
    } catch (IKnowWhatToDoWithThisException e) { 
     handle(e); 
    } catch (SQLException ex) { 
     throw ex; 
    } catch (IOException ex) { 
     throw ex; 
    } catch (Throwable t) { 
     throw new RuntimeException(t); 
    } 
} 

Ver también:

+5

La segunda versión del método que escribió no es equivalente ... que había necesidad de añadir dos más 'bloques catch' que acaba de volver a lanzar la excepción ... uno para' RuntimeException' y otro para ' Error'. 'Throwables.propagate' solo envuelve lo que se puede arrojar en' RuntimeException' si aún no es una excepción no seleccionada. – ColinD

+0

Todavía no lo entiendo. ¿Por qué quiero capturar una excepción si quiero propagarlo de todos modos? Puedo hacer: public void doSomething() arroja IOException, SQLException {try {someMethodThatCouldThrowAnything(); } catch (IKnowWhatToDoWithThisException e) {handle (e); }}. Este no es un ejemplo real ... –

+1

@Jeny: No se puede hacer así, 'someMethodThatCouldThrowAnything()' puede arrojar algunas excepciones marcadas que no sean 'IOException' y' SQLException'. – axtavt

2

He revisado la documentación de Guava Throwables y no los he encontrado realmente útiles. Usar throw new RuntimeException (e) es más simple de comprender que Throwables.propagate(), en el escenario en el que desea lanzar una excepción no verificada que envuelve una excepción marcada.

+0

No es necesario que compruebe si su throwable es una excepción comprobada específica, una de tiempo de ejecución o un error. Impide demasiadas encapsulaciones arrojables. No es inusual ver kilómetros de RuntimeException envueltos, lo que lleva a un seguimiento de pila muy largo. Y finalmente ver que lo último tiene valor. – LoganMzz

0

Un escenario que puedo proporcionarle a cualquiera que lo encuentre útil es que si tiene un método que envuelve las excepciones lanzadas, esto puede usarse para desenvolver/convertir la causa en una excepción específica.

Ejemplo: el método get en Guava's LoadingCache ajusta todas las excepciones marcadas en ExecutionException. La documentación indica que la excepción puede inspeccionarse usando getCause().

Aquí Throwables.propagateIfInstanceOf puede usarse para lanzar excepciones específicas para el método de llamada de manejar, si sabemos que cache.get() arrojará esas excepciones (quizá específicas para LoadingCache, pero si el valor es misisng, la memoria caché intenta cargar un valor que puede tirar excepciones marcadas).

public String getCacheValue(String key) throws SQLException{ 
    try{ 
     return cache.get(key); 
    }catch(ExecutedException ex){ 
     Throwables.propagateIfInstanceOf(ex.getCause(), SQLException.class); 
     Throwables.propagate(ex); 
    } 
} 
Cuestiones relacionadas