Guava缓存和保留已检查异常 (注:该内容为一个提问标题,无需回答)

24

我正在重构一些代码,以使用Guava Cache

初始代码:

public Post getPost(Integer key) throws SQLException, IOException {
    return PostsDB.findPostByID(key);
}
为了不破坏任何东西,我需要保留所有抛出的异常,而不进行包装。
当前的解决方案看起来有些丑陋:
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);
        }
    }
}

有没有可能让它更好看一些呢?

2个回答

39

在编写问题后,我开始考虑使用泛型的实用方法。然后想起了关于 Throwables 的一些内容。是的,它已经存在了!)

可能还需要处理UncheckedExecutionException 或者 ExecutionError

所以解决方案是:

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

非常好!

还可以参考ThrowablesExplainedLoadingCache.getUnchecked为什么我们弃用 Throwables.propagate


犹豫是否应该发布自问自答的问题。但是这篇文章很明确:http://meta.stackexchange.com/questions/2706/posting-and-answering-questions-you-have-already-found-the-answer-to - Vadzim
1
请注意,如果e.getCause()是RuntimeException或Error,则上述代码将抛出它而不是IllegalStateException(e)。此答案中的代码与问题中的原始代码匹配,但是,如果由于某种奇怪的原因,您总是希望将所有非SQL和非IO异常都包装成IllegalStateException,则需要使用自定义代码。 - Niraj Tolia
@Niraj,当然。 throw new IllegalStateException(e); 这里是死代码行,只是为了让编译器高兴。 - Vadzim

-1

只需使用Lombok中的@SneakyThrows。 不再需要强制异常包装的问题。

<抱怨> 现在是2021年,Java仍然有受检异常...人们何时才能明白,即使受检异常在理论上看起来很好,但在实践中会创建太多问题呢?

长期解决方案:如果有机会,请转向像Kotlin这样的适当语言。 </抱怨>


请注意,在这种情况下,@SneakyThrows不会解开ExecutionException - Vadzim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接