Mat*_*eak 5 java exception finally
我正在从 Java 语言规范中考虑这一点:
如果 catch 块由于原因 R 突然完成,则执行 finally 块。然后有一个选择:
如果 finally 块正常完成,则 try 语句由于原因 R 突然完成。
如果 finally 块因原因 S 突然完成,则 try 语句因原因 S 突然完成(并且原因 R 被丢弃)。
我有一个块如下:
try {
.. do stuff that might throw RuntimeException ...
} finally {
try {
.. finally block stuff that might throw RuntimeException ...
} catch {
// what to do here???
}
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,我希望块中的任何RuntimeException抛出finally都能逃脱,前提是它不会导致RuntimeException主try块中的抛出被丢弃。
Java 中有什么方法可以让我知道与块关联的finally块是否正常完成?
我猜我可以将 a 设置boolean为主try块的最后一个语句(例如,completedNormally = true这是最好的方法,还是有更好/更标准的东西?
我相信关键是不要失去原来的原因。
如果我们看看 try-with-resources 的行为:
private static class SomeAutoCloseableThing implements AutoCloseable {
@Override
public void close() {
throw new IllegalStateException("closing failed");
}
}
public static void main(String[] args) {
try (SomeAutoCloseableThing thing = new SomeAutoCloseableThing()) {
throw new IllegalStateException("running failed");
}
}
Run Code Online (Sandbox Code Playgroud)
我们最终得到:
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:16)
Suppressed: java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:17)
Run Code Online (Sandbox Code Playgroud)
这个堆栈跟踪很棒,因为我们看到了两个异常,即我们不会丢失running failed一个。
在没有 try-with-resources 的情况下实现这一点,错误的方式:
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:16)
Suppressed: java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:17)
Run Code Online (Sandbox Code Playgroud)
我们最终得到:
Exception in thread "main" java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:9)
at Main.main(Main.java:19)
Run Code Online (Sandbox Code Playgroud)
我们不知道这种running failed情况也发生了,因为我们打破了控制流,如果您需要调试这种情况,那是非常糟糕的。
在没有 try-with-resources 的情况下实现这一点,正确的方法(在我看来)是“记录并忘记”finally块中发生的异常:
public static void main(String[] args) {
SomeAutoCloseableThing thing = new SomeAutoCloseableThing();
try {
throw new IllegalStateException("running failed");
} finally {
thing.close();
}
}
Run Code Online (Sandbox Code Playgroud)
我们最终得到:
17:10:20.030 [main] ERROR Main - An error occurred while closing SomeAutoCloseableThing
java.lang.IllegalStateException: closing failed
at Main$SomeAutoCloseableThing.close(Main.java:10) ~[classes/:?]
at Main.main(Main.java:21) [classes/:?]
Exception in thread "main" java.lang.IllegalStateException: running failed
at Main.main(Main.java:18)
Run Code Online (Sandbox Code Playgroud)
不如 try-with-resources 方法,但至少我们知道实际发生了什么,没有丢失任何东西。
| 归档时间: |
|
| 查看次数: |
158 次 |
| 最近记录: |