I need to do some initialization and clean it up in case of any exception. I'd still like the exception to be passed to the caller. The problem is I now have to declare this method as throws Throwable
and then I have to explicitly handle this throwable in the caller, just as if开发者_StackOverflow all procedures don't throw Throwable
s implicitly already. Stupid isn't it?
try {
init_step1();
init_step2();
}
catch (Throwable th) {
clean();
throw th;
}
One way of doing this is to perform the cleanup in a finally block instead, noticing whether there's been an exception by whether you actually got to the end of the try block or not:
boolean success = false;
try {
// Stuff here
success = true;
} finally {
if (!success) {
clean();
}
}
Stupid is fighting against checked exceptions. You have to throw something different if you don't want to require every caller to handle it. just throw a RuntimeException
public void myMethod() throws RuntimeException {
try {
init_step1();
init_step2();
}
catch (Throwable th) {
clean();
throw new RuntimeException(th);
}
}
why do you catch Throwable in first place anyway? init_step1() and init_step2() doesn't throw an exception?
@Jon Skeet's solution is the cleanest. Another solution which may interest you.
try {
// Stuff here
} catch(Throwable t) {
clean(t);
// bypasses the compiler check
Thread.currentThread().stop(t);
}
I would only suggest using this approach if you needed to know the exception thrown. e.g. For resources I have which are closable, I record the exception which triggered their close. This way if I try to use the resource and it is closed I can see why it is closed.
private void checkClosed() {
if (closed)
throw new IllegalStateException("Closed", reasonClosed);
}
精彩评论