Guava:Throwables.propagate和InterruptedException

14

当使用Guava中的Throwables.propagate(e)时,如何处理InterruptedException最佳实践是什么?

我喜欢在没有抛出已检查异常且异常处理由调用者负责的方法中使用Throwables.propagate(e),但它不能像我期望的那样处理InterruptedException。

我不想失去线程被中断的信息,因此我最终会写出类似以下的代码:

public void run() {
    Callable c = ...;
    try {
        c.call();
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        throw Throwables.propagate(e);
    } catch (Exception e) {
        throw Throwables.propagate(e);
    }
}

在Guava中有没有这样做的方法?是否有一种(向后兼容的?!)方法可以使用类似Throwables.propagate()的东西,如果它正在包装和传播InterruptedException,它会将线程设置为中断状态?


1
我会在Guava内部提出这个功能请求。 - artbristol
1个回答

8
方便地说,我们曾在内部讨论过这个问题。我将复制并粘贴以下内容:
我对Throwables.propagate(e)的强硬意见是它基本上就是throw new RuntimeException(e),人们通常不应该这样做,就像他们通常不应该编写throw new RuntimeException(e)一样。(如果他们要写,他们可能会直接写出来,以便清楚地了解正在发生的事情。)
我对catch(Exception e)的强硬观点——通常是人们陷入困境的方式——也是他们通常不应该这样做。(显然有一些情况下catch(Exception e)是显然正确的(基本上是任何顶层操作范围的catch块),但那些都是...显而易见的。)
我对InterruptedException的强硬观点是,InterruptedException实现Exception本身就有缺陷:它需要其他异常所没有的特殊处理。
我对将InterruptedException转换为RuntimeException的看法是“不要”。 (就像我上面说的其他东西一样,这也是有争议的。)
因此,一方面,我不确定我们是否能拯救propagate()。另一方面,也许将该方法变得稍微好一点会很好。
另外,请考虑以下调用程序,它捕获ExecutionException e:
throw Throwables.propagate(e.getCause());
中断使用者线程是错误的,就像直接抛出e.getCause()一样,因为中断是针对计算线程而不是使用者线程的。
我倾向于不改变propagate()。(正如您可能猜到的那样,我个人倾向于废弃它,但这是一个更大的讨论。)

1
+1 有趣的观点。我很惊讶人们会写throw Throwables.propagate(e.getCause());!堆栈跟踪看起来就像所有事情都发生在单个线程中! - artbristol
1
谢谢,有趣的观点。InterruptedException实现为Exception是错误的,但Java就是这样。我认为将InterruptedException转换为RuntimeException有时是必要的:如果我的方法签名由外部接口固定(因此无法抛出InterruptedException),并且我的操作被中断(因此无法履行合同),我必须抛出异常。除了将线程设置为中断并抛出RuntimeException之外,还有什么其他明智的选择呢? - Aled Sage
4
为了替代使用异常包装异常的写法 throw new RuntimeException(e),这种做法会造成无用的干扰(尤其是当它未添加任何有用的信息,如当前上下文的附加消息时)。只要能避免这种干扰(例如,已经是非检查异常),那就太好了。有一派人认为API应该尽可能使用非检查异常。即使一个人不赞同这个观点,他仍然必须实现其他人以这种方式编写的接口。所以请不要废弃 Throwables.propagate(e) - Aled Sage
1
我认为在处理抛出已检查异常的 API 时,与其将异常添加到方法签名中,不如使用 throw Throwables.propagate(e); 更好。我认为这是一种很好的惯用方式,表达了“这里没有特别的问题,将其视为正常的执行问题”的意思。 - Pierre-Henri

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