番石榴缓存和保留已检查的异常

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

初始代码:

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

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


答案 1

写完这个问题后,问题开始考虑用泛型驱动的实用程序方法。然后想起了一些关于Throwables的事情。是的,它已经在那里了!)

可能还需要处理UncheckedExecutionException甚至Experor

所以解决方案是:

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.getUncheckedWhy we deprecats throwables.propagate


答案 2

只需从龙目岛使用。强制异常包装不再有问题。@SneakyThrows

<咆哮>现在是2021年,Java仍然检查异常...人们什么时候才能明白,即使检查的异常在纸面上看起来不错,它们在实践中也会产生太多的问题?

长期解决方案:如果有机会,请改用适当的语言,如 Kotlin。</咆哮>