问题
I'm refactoring some code to use guava Cache.
Initial code:
public Post getPost(Integer key) throws SQLException, IOException {
return PostsDB.findPostByID(key);
}
In order not to break something I need to preserve any thrown exception as is, without wrapping it.
Current solution appears somewhat ugly:
public Post getPost(final Integer key) throws SQLException, IOException {
try {
return cache.get(key, new Callable<Post>() {
@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);
}
}
}
Is there any possible way to make it nicer?
回答1:
Just after writing the question started thinking about utility method powered with generics. Then remembered something about Throwables. And yes, it's already there! )
It may also be necessary to handle UncheckedExecutionException or even ExecutionError.
So the solution is:
public Post getPost(final Integer key) throws SQLException, IOException {
try {
return cache.get(key, new Callable<Post>() {
@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);
}
}
Very nice!
See also ThrowablesExplained, LoadingCache.getUnchecked and Why we deprecated Throwables.propagate.
来源:https://stackoverflow.com/questions/8645965/guava-cache-and-preserving-checked-exceptions