番石榴缓存并保留已检查的exception

我正在重构一些使用番石榴缓存的代码。

初始代码:

public Post getPost(Integer key) throws SQLException, IOException { return PostsDB.findPostByID(key); } 

为了不破坏某些东西,我需要保留任何抛出的exception,而不包装它。

目前的解决方案看起来有些难看

 public Post getPost(final Integer key) throws SQLException, IOException { try { return cache.get(key, new Callable() { @Override public Post call() throws Exception { return PostsDB.findPostByID(key); } }); } catch (ExecutionException e) { Throwable cause = e.getCause(); if (cause instanceof SQLException) { throw (SQLException) cause; } else if (cause instanceof IOException) { throw (IOException) cause; } else if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } else { throw new IllegalStateException(e); } } } 

有没有办法让它变得更好?

在写完问题之后,开始考虑使用generics的实用方法。 然后想起了关于Throwables的一些事情。 是的,它已经存在了! )

可能还需要处理UncheckedExecutionException甚至ExecutionError 。

所以解决方案是:

 public Post getPost(final Integer key) throws SQLException, IOException { try { return cache.get(key, new Callable() { @Override public Post call() throws Exception { return PostsDB.findPostByID(key); } }); } catch (ExecutionException e) { Throwables.propagateIfPossible( e.getCause(), SQLException.class, IOException.class); throw new IllegalStateException(e); } catch (UncheckedExecutionException e) { Throwables.throwIfUnchecked(e.getCause()); throw new IllegalStateException(e); } } 

非常好!

另见ThrowablesExplained 。

另请参阅为什么我们弃用Throwables.propagate和LoadingCache.getUnchecked 。