如果您有一些需要运行的清理代码,无论是否抛出异常,try { ... } finally { ... }
都是您需要的。但是,如果您希望清理代码仅在发生异常时运行,该怎么办?
一种可能的解决方案是:
boolean ok = false;
try {
doWork();
ok = true;
} finally {
if (!ok) {
doCleanup();
}
}
它完全符合我的要求,但我想知道是否有更自然的方式来表达这个想法。
这个替代方案没有通过集合:
try {
doWork();
} catch (Throwable e) {
doCleanup();
throw e; // BAD: Cant do this unless the enclosing function is declared to throw Throwable
}
我想我可以捕获Exception而不是Throwable,但我不喜欢非Exception throwable会绕过清理代码的想法。毕竟,即使对于非Exception throwable,常规finally
块仍然会运行。
除此之外:在C ++中,您只需使用 catch-all 块:
try {
doWork();
} catch (...) {
doCleanup();
throw;
}
答案 0 :(得分:6)
从Java 7开始,这是合法代码:
public static void method() {
try {
// stuff which doesn't declare checked exceptions
} catch (Throwable t) {
throw t;
}
}
改进的语言规则允许这样做,因为静态分析可以证明t
实际上不会是任何已检查的异常。
同样,您只需要声明最小必要的已检查例外:
public static void method() throws IOException {
try {
throwingMethod();
} catch (Throwable t) { throw t; }
}
static void throwingMethod() throws IOException {}
答案 1 :(得分:4)
如果您有try
... finally
阻止,则适用以下两种情况之一:
throws
子句,而try
块可能会抛出已检查的异常。拥有catch
阻止RuntimeException
和任何已检查例外的阻止:
catch (RuntimeException | YourCheckedException e) {
// Cleanup
throw e;
}
throws
子句,try
块只能抛出未经检查的异常。 Catch RuntimeException
,不需要在throws
中声明。
catch (RuntimeException e) {
// Cleanup
throw e;
}
答案 2 :(得分:1)
它完全符合我的要求,但我想知道是否有更自然的方式来表达这个想法。
语言具有独特的语法结构。在Java中,您展示了第一个选项:
boolean ok = false;
try {
doWork();
ok = true;
} finally {
if (!ok) {
doCleanup();
}
}
这是惯用的用Java做的方式,感觉自然(无双关语)自然所述语言的语法。
您正在寻找一种自然的on-error only机制,Java没有。您正在尝试创建一个清理机制,而不涉及对已检查的throwable进行编译器检查。有人会想使用泛型,但泛型有限制(即,不能参数化throwable的子类。)
但是,IIRC,有一些方法可以通过使用Class参数化封闭方法来绕过编译器检查,然后通过反射制作实例并抛出它。但是,在一般情况下,现在我们正在进入毛茸茸的领域,没有明显和有用的原因。
我会坚持你所展示的榜样。很清楚它的作用是什么,它是干净的,并且没有asinine和意想不到的陷阱。
.PS。
对于对上帝的爱,我希望你没有使用C ++全能的习惯用法(至少在没有使用一系列特定类型的catch块之前,包括std :: exception)。
没有什么比处理到达这样一个全能块的代码更糟糕了。没有任何奇怪的信息,几乎不可能追踪扔掉它的东西。
去过那里并且不以此为生。噩梦的东西。