java - 我的安全重新抛出有多安全?

标签 java exception

(后期编辑:这个问题有望在 Java 7 出现时过时,因为 "final rethrow" featureseems like it will be added。)


我经常遇到这样的情况:

    do some initialization
    try {
        do some work 
    } catch any exception {
        undo initialization
        rethrow exception
    }

In C# you can do it like this:

InitializeStuff();
try
{
    DoSomeWork();
}
catch 
{
    UndoInitialize();
    throw;
}

对于 Java,没有好的替代品,因为 the proposal for improved exception handling was cut from Java 7 ,看起来最多需要几年时间才能得到类似的东西。因此,我决定推出自己的产品:

(编辑: 半年后,final rethrow is back,或者看起来是这样。)

public final class Rethrow {

    private Rethrow() { throw new AssertionError("uninstantiable"); }

    /** Rethrows t if it is an unchecked exception. */
    public static void unchecked(Throwable t) {
        if (t instanceof Error)
            throw (Error) t;
        if (t instanceof RuntimeException)
            throw (RuntimeException) t;
    }

    /** Rethrows t if it is an unchecked exception or an instance of E. */
    public static <E extends Exception> void instanceOrUnchecked(
            Class<E> exceptionClass, Throwable t) throws E, Error,
            RuntimeException {
        Rethrow.unchecked(t);
        if (exceptionClass.isInstance(t))
            throw exceptionClass.cast(t);
    }

}

典型用法:

public void doStuff() throws SomeException {
    initializeStuff();
    try {
        doSomeWork();
    } catch (Throwable t) {
        undoInitialize();
        Rethrow.instanceOrUnchecked(SomeException.class, t);
        // We shouldn't get past the above line as only unchecked or 
        // SomeException exceptions are thrown in the try block, but
        // we don't want to risk swallowing an error, so:
        throw new SomeException("Unexpected exception", t); 
    }
    private void doSomeWork() throws SomeException { ... }
}

有点罗嗦,捕获Throwable通常是不受欢迎的,我不太乐意使用反射来重新抛出异常,我总是觉得写“这不会发生”有点不安"评论,但在实践中它运作良好(或至少看起来如此)。我想知道的是:

  1. 我的 rethrow 辅助方法有什么缺陷吗?我错过了一些角落案例? (我知道 Throwable 可能是由严重到我的 undoInitialize 会失败的原因引起的,但没关系。)
    • 有人已经发明了这个吗?我看了 Commons Lang 的 ExceptionUtils但这还有其他事情。

编辑:

  • finally 不是我要找的机器人。我只对抛出异常时感兴趣。
  • 是的,我知道捕获 Throwable 是一个很大的禁忌,但我认为与具有三个 catch 子句(对于 ErrorRuntimeExceptionSomeException,分别)具有相同的代码。
  • 请注意,我并不是要抑制任何错误 - 我的想法是,一旦我倒回一个几件事。

最佳答案

有几种方法可以处理这个问题。如果您不需要知道异常是什么,我倾向于第一个。

boolean okay = false;
try {
  // do some work which might throw an exception
  okay = true;
} finally {
  if (!okay) // do some clean up.
}

在某些情况下,您可以在没有额外变量的情况下执行相同的操作,具体取决于 try block 的作用。

第二种选择是 hack,但也有效。

try {
    // do some work which might throw an exception
} catch (Throwable t) {
    // do something with t.
    Thread.currentThread().stop(t);
}

stop(Throwable t) 方法不会停止线程,而是导致线程抛出以未经检查的方式提供的异常。

您可以稍微调整一下使用 Unsafe.throwException() 并且有一种方法可以使用我忘记的泛型来做到这一点。

关于java - 我的安全重新抛出有多安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1650835/

相关文章:

c++ - 如果没有 uncaught_exception,C++ 析构函数中的异常

java - java中的前置条件与后置条件?

java - Storm 三叉戟 : How to use IPartitionedTridentSpout?

java - 如果我的程序中有多个线程,每个线程在技术上是否都有自己的堆栈?每个线程都有自己的堆吗?

java - 处理方法异常类型参数的最有效方法是什么

c++ - 抛出的对象复制构造——为什么?

Eclipse 上的 Java 构建路径错误

java - 如何使用 java-selenium 中的 cucumber bdd 框架处理 Bootstrap 下拉列表

当只有一个直接 child 时,Java 返回 "ScrollView can host only one direct child"

c# - C# 中的索引越界异常