Guava 缓存和保留检查的异常

Posted

技术标签:

【中文标题】Guava 缓存和保留检查的异常【英文标题】:Guava cache and preserving checked exceptions 【发布时间】: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);
        
    

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

【问题讨论】:

【参考方案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);
    

非常好!

另请参阅ThrowablesExplained、LoadingCache.getUnchecked 和 Why 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

以上是关于Guava 缓存和保留检查的异常的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Guava的缓存管理

Guava LoadingCache不能缓存null值

使用google guava做内存缓存

google guava缓存分析

Guava cache使用总结

Java内存缓存-通过Google Guava创建缓存