(后期编辑:这个问题将有望被淘汰时的Java 7自带因为的,"最终重投"功能,这似乎将被添加.)
很多时候,我发现自己处于这样的情况:
do some initialization try { do some work } catch any exception { undo initialization rethrow exception }
在C#中你可以这样做:
InitializeStuff(); try { DoSomeWork(); } catch { UndoInitialize(); throw; }
对于Java来说,没有很好的替代,并且由于改进的异常处理的提议是从Java 7中删除的,所以看起来好几年才能得到类似的东西.因此,我决定自己动手:
(编辑: 半年后,最后的重新抛出回来了,或者看起来如此.)
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 staticvoid instanceOrUnchecked( Class 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
通常不赞成,我真的很高兴使用反射只是为了重新抛出异常,我总是觉得有点不安写"这不会发生"的评论,但在实践中它运作良好(或似乎,至少).我想知道的是:
我的重新抛出辅助方法有任何缺陷吗?我错过了一些角落案件?(我知道这Throwable
可能是由于某种严重的事情导致我的undoInitialize
意志失败,但那没关系.)
有人已经发明了这个吗?我看了Commons Lang的,ExceptionUtils
但那还有其他的事情.
编辑:
finally
不是我正在寻找的机器人.抛出异常时我只对做事情感兴趣.
是的,我知道捕Throwable
是一个很大的禁忌,但我认为这是两害取其轻这里相比具有三个catch子句(对Error
,RuntimeException
和SomeException
,分别)具有相同的代码.
请注意,我并没有试图压制任何错误 - 我的想法是,try
只要我重新启动了一些内容,块中抛出的任何异常都会继续通过调用堆栈冒出来.
Peter Lawrey.. 5
有两种方法可以解决这个问题.如果您不需要知道异常是什么,首先是我的偏好.
boolean okay = false; try { // do some work which might throw an exception okay = true; } finally { if (!okay) // do some clean up. }
在某些情况下,您可以在没有额外变量的情况下执行相同操作,具体取决于try块的功能.
第二个选择是黑客,但也有效.
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()进行一些摆弄,并且有一种方法可以使用Generics执行此操作,我已经忘记了.
有两种方法可以解决这个问题.如果您不需要知道异常是什么,首先是我的偏好.
boolean okay = false; try { // do some work which might throw an exception okay = true; } finally { if (!okay) // do some clean up. }
在某些情况下,您可以在没有额外变量的情况下执行相同操作,具体取决于try块的功能.
第二个选择是黑客,但也有效.
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()进行一些摆弄,并且有一种方法可以使用Generics执行此操作,我已经忘记了.