我有以下代码:
try{
line1; // can throw exception
line2; // can throw exception
line3; // can throw exception
line4; // can throw exception
}catch(Exception e){
handle exception;
}finally{
do remaining stuffs;
}
即使上面的行出现异常,我也需要在try块中执行所有4行。
假设代码在try块的line2中遇到了异常,即使这样我也需要执行line3和line4(这又会引发异常)。有没有一种简单的方法可以代替多个try-catch块。
答案 0 :(得分:1)
如果需要,可以在外部try / catch块中包含try / catch块。像这样:
try{
line1; // can throw exception
try {
line2; // can throw exception
} catch (Exception e) {
if (e is a really bad one) throw e; // don't continue
else System.out.println("line2 failed but I'll keep going");
}
try {
line3; // can throw exception
} catch (Exception e) {
if (e is a really bad one) throw e; // don't continue
else System.out.println("line3 failed but I'll keep going");
}
line4; // can throw exception
}catch(Exception e){
handle exception;
}finally{
do remaining stuffs;
}
答案 1 :(得分:1)
try with resource语句允许以简洁的语法(与嵌套的finally
块相比)指定即使在特殊情况下也应执行的动作。它还具有另一个优点:当多个操作失败时,异常不会相互影射,而是在主要的可抛出对象处注册为suppressed可抛出对象。缺点是资源是按照创建时的相反顺序关闭的,因此我们必须反转行的顺序:
public static void main(String[] args) {
for(int test = 0; test < 16; test++) {
int currentTest = test;
System.out.println("Test "+currentTest);
try(AutoCloseable c1 = () -> line4(currentTest); // 4
AutoCloseable c2 = () -> line3(currentTest); // 3
AutoCloseable c3 = () -> line2(currentTest)) { // 2
line1(currentTest); // 1
}
catch(Exception ex) {
System.out.print("got exception ");
ex.printStackTrace(System.out);
}
System.out.println();
}
}
public static void line1(int whichTest) {
if((whichTest & 1) != 0) {
System.out.println("letting line 1 fail");
throw new RuntimeException("line 1 failed");
} else System.out.println("line1 executed");
}
public static void line2(int whichTest) {
if((whichTest & 2) != 0) {
System.out.println("letting line 2 fail");
throw new RuntimeException("line 2 failed");
} else System.out.println("line2 executed");
}
public static void line3(int whichTest) {
if((whichTest & 4) != 0) {
System.out.println("letting line 3 fail");
throw new RuntimeException("line 3 failed");
} else System.out.println("line3 executed");
}
public static void line4(int whichTest) {
if((whichTest & 8) != 0) {
System.out.println("letting line 4 fail");
throw new RuntimeException("line 4 failed");
} else System.out.println("line4 executed");
}
此示例程序在所有可能的情况下运行。我缩短了输出以仅显示一些示例:
Test 0
line1 executed
line2 executed
line3 executed
line4 executed
Test 1
letting line 1 fail
line2 executed
line3 executed
line4 executed
got exception java.lang.RuntimeException: line 1 failed
at SafeActions.line1(SafeActions.java:23)
at SafeActions.main(SafeActions.java:10)
Test 9
letting line 1 fail
line2 executed
line3 executed
letting line 4 fail
got exception java.lang.RuntimeException: line 1 failed
at SafeActions.line1(SafeActions.java:23)
at SafeActions.main(SafeActions.java:10)
Suppressed: java.lang.RuntimeException: line 4 failed
at SafeActions.line4(SafeActions.java:41)
at SafeActions.lambda$main$0(SafeActions.java:7)
at SafeActions.main(SafeActions.java:7)
Test 15
letting line 1 fail
letting line 2 fail
letting line 3 fail
letting line 4 fail
got exception java.lang.RuntimeException: line 1 failed
at SafeActions.line1(SafeActions.java:23)
at SafeActions.main(SafeActions.java:10)
Suppressed: java.lang.RuntimeException: line 2 failed
at SafeActions.line2(SafeActions.java:29)
at SafeActions.lambda$main$2(SafeActions.java:9)
at SafeActions.main(SafeActions.java:7)
Suppressed: java.lang.RuntimeException: line 3 failed
at SafeActions.line3(SafeActions.java:35)
at SafeActions.lambda$main$1(SafeActions.java:8)
at SafeActions.main(SafeActions.java:7)
Suppressed: java.lang.RuntimeException: line 4 failed
at SafeActions.line4(SafeActions.java:41)
at SafeActions.lambda$main$0(SafeActions.java:7)
at SafeActions.main(SafeActions.java:7)
直接使用AutoCloseable
接口的一个缺点是,它声明可能抛出Exception
,因此迫使我们抓住Exception
。如果操作未引发检查异常或非常特殊的类型,则创建扩展AutoCloseable
的自己的功能接口(对于IOException
,已经有java.io.Closeable
)很有用。 / p>
interface MyAction extends AutoCloseable {
@Override public void close();
}
public static void main(String[] args) {
int currentTest = 11;
try(MyAction c1 = () -> line4(currentTest);
MyAction c2 = () -> line3(currentTest);
MyAction c3 = () -> line2(currentTest)) {
line1(currentTest);
}
}
由于该示例未捕获异常,因此我还删除了无论如何在第二次迭代之后都不会执行的循环。
letting line 1 fail
letting line 2 fail
line3 executed
letting line 4 fail
Exception in thread "main" java.lang.RuntimeException: line 1 failed
at SafeActions.line1(SafeActions.java:17)
at SafeActions.main(SafeActions.java:11)
Suppressed: java.lang.RuntimeException: line 2 failed
at SafeActions.line2(SafeActions.java:23)
at SafeActions.lambda$main$2(SafeActions.java:10)
at SafeActions.main(SafeActions.java:8)
Suppressed: java.lang.RuntimeException: line 4 failed
at SafeActions.line4(SafeActions.java:35)
at SafeActions.lambda$main$0(SafeActions.java:8)
at SafeActions.main(SafeActions.java:8)