【问题标题】:Guava cache and preserving checked exceptionsGuava 缓存和保留检查的异常
【发布时间】:2012-01-28 13:53:49
【问题描述】:

我正在重构一些代码以使用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);
        }
    }
}

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

【问题讨论】:

    标签: java caching exception-handling guava checked-exceptions


    【解决方案1】:

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

    可能还需要处理UncheckedExecutionException or even 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.getUncheckedWhy we deprecated Throwables.propagate

    【讨论】:

    • 犹豫是否应该发布自我回答的问题。但这很清楚:meta.stackexchange.com/questions/2706/…
    • 请注意,如果 e.getCause() 是 RuntimeException 或 Error,上述代码将抛出该异常而不是 IllegalStateException(e)。此答案中的代码与问题中的原始代码匹配,但如果出于某种奇怪的原因,总是想将所有非 SQL 和非 IO 异常包装到 IllegalStateException 中,则需要自定义代码。
    • @Niraj,当然。 throw new IllegalStateException(e); 这是为了让编译器高兴的死代码行。
    【解决方案2】:

    只需使用来自 Lombok 的 @SneakyThrows。 强制异常包装不再有问题。

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

    长期解决方案:如果有机会,请改用合适的语言,例如 Kotlin。

    【讨论】:

    • 请注意,@SneakyThrows 在这种情况下不会解开 ExecutionException
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-04
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多