2011-02-23 78 views
14

The javadoc example如何使用Google Guava的Throwables.propagateIfInstanceOf()?

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

也不是很具体的。真正的程序将如何?我真的不明白方法Throwables.propagateIfInstanceOf(Throwable, Class),propagate(),propagateIfPossible()的目的。我什么时候使用它们?

回答

15

这些方法的目的是提供一种方便的方式来处理检查的异常。

Throwables.propagate()是retrowing检查异常的常用方法的简写,包装成未选中的异常(为了避免在方法的throws子句中声明它)。

Throwables.propagateIfInstanceOf()用于重新检查异常,因为它们的类型在方法的throws子句中声明。

换句话说,在问题

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); 
    } 
} 

的代码是用于以下的代码的简写:

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); 
    } 
} 

参见:

+5

你写的方法的第二个版本不是等价的......你需要添加两个'catch'块来重新抛出异常......一个用于'RuntimeException'和一个用于' Error'。如果Throwables.propagate不是未经检查的异常,则Throwables.propagate只会将该throwable包装在“RuntimeException”中。 – ColinD 2011-02-23 14:37:58

+0

我还是不会动心的。为什么我想要捕捉一个异常,如果我想传播它呢?我可以这样做:public void doSomething()throws IOException,SQLException {try {someMethodThatCouldThrowAnything(); catch(IKnowWhatToDoWithThisException e){handle(e); }}。这不是一个真正的例子... – 2011-02-25 01:55:57

+1

@Jeny:你不能这样做是'someMethodThatCouldThrowAnything()'可以抛出一些除了'IOException'和'SQLException'以外的检查异常。 – axtavt 2011-02-25 09:19:09

2

我已经浏览了Guava Throwables的文档,但我没有发现它们真的有用。使用throw new RuntimeException(e)比Throwables.propagate()更容易理解,在这种情况下,您想抛出一个未检查的异常来包装检查的异常。

+0

你不必检查你的throwable是一个特定的检查异常,一个运行时错误还是一个错误。它防止了太多的可抛封装。看到包装的RuntimeException导致需要经过很长的堆栈跟踪的公里并不罕见。最后看到唯一的最后一个有价值。 – LoganMzz 2015-08-17 09:02:05

0

我可以提供给任何人会发现这个有用的一个场景是,如果你有一个方法包装抛出的任何异常,那么这可以用来解包/将原因转换为特定的异常。

示例:Guava的LoadingCache中的get方法将所有检查的异常包装为ExecutionException。该文档指出,可以使用getCause()检查异常。

这里Throwables.propagateIfInstanceOf可以用来抛出特定的异常的调用方法来处理,如果我们知道cache.get()将抛出的异常(也许具体到LoadingCache,但如果价值是misisng,缓存尝试加载一个值,从而可以抛出检查异常)。

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