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

javadoc示例

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()方法的目的。 我什么时候使用它们?

这些方法的目的是提供一种处理已检查exception的便捷方法。

Throwables.propagate()是将已检查exception包含在未经检查的exception中的常用习惯用法的简写(以避免在方法的throws子句中声明它)。

如果在方法的throws子句中声明了它们的类型,则Throwables.propagateIfInstanceOf()用于转发已检查的exception。

换句话说,有问题的代码

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

也可以看看:

  • 已检查与未检查的exception
  • 针对已检查exception的案例

我已经阅读了Guava Throwables的文档,但我发现它们并没有真正有用。 使用throw new RuntimeException(e)比Throwables.propagate()更容易理解,在你想要抛出一个包含已检查exception的未经检查的exception的场景中。

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

示例:Guava的LoadingCache中的get方法将所有已检查的exception包装到ExecutionException中 。 文档说明可以使用getCause()检查exception。

这里Throwables.propagateIfInstanceOf可用于抛出调用方法要处理的特定exception,如果我们知道cache.get()将抛出这些exception(可能特定于LoadingCache,但如果值为misisng,则缓存尝试加载值这可以抛出已检查的exception)。

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