(后期编辑:这个问题有望在 Java 7 出现时过时,因为 "final rethrow" feature 是 seems 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
通常是不受欢迎的,我不太乐意使用反射来重新抛出异常,我总是觉得写“这不会发生”有点不安"评论,但在实践中它运作良好(或至少看起来如此)。我想知道的是:
- 我的 rethrow 辅助方法有什么缺陷吗?我错过了一些角落案例? (我知道
Throwable
可能是由严重到我的undoInitialize
会失败的原因引起的,但没关系。)- 有人已经发明了这个吗?我看了 Commons Lang 的
ExceptionUtils
但这还有其他事情。
- 有人已经发明了这个吗?我看了 Commons Lang 的
编辑:
finally
不是我要找的机器人。我只对抛出异常时感兴趣。- 是的,我知道捕获
Throwable
是一个很大的禁忌,但我认为与具有三个 catch 子句(对于Error
,RuntimeException
和SomeException
,分别)具有相同的代码。 - 请注意,我并不是要抑制任何错误 - 我的想法是,一旦我倒回一个几件事。
最佳答案
有几种方法可以处理这个问题。如果您不需要知道异常是什么,我倾向于第一个。
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/