简体   繁体   English

在异常情况下执行 try 块中的剩余代码

[英]execute remaining code in try block in case of exception

I have the following code:我有以下代码:

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;
}

I need to execute all 4 lines inside try block even in case of exception from above lines.即使上面的行出现异常,我也需要在 try 块中执行所有 4 行。

Suppose the code encountered an exception in line2 of try block, even then I need to execute line3 and line4(which in turn can throw exceptions).假设代码在 try 块的 line2 中遇到异常,即使这样我也需要执行 line3 和 line4(这反过来又会抛出异常)。 Is there an easy way to do this instead of having multiple try-catch blocks.有没有一种简单的方法来代替拥有多个 try-catch 块。

You can have try/catch blocks within the outer try/catch block if it makes sense to.如果有意义的话,您可以在外部 try/catch 块中包含 try/catch 块。 Something like this:像这样的东西:

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;
}

The try with resource statement allows to specify actions that ought be executed even in the exceptional case, with a concise syntax (compared to nested finally blocks). try with resource语句允许使用简洁的语法(与嵌套的finally块相比)指定即使在例外情况下也应该执行的操作。 It also has another advantage: when multiple actions fail, the exceptions do not shadow each other but get registered as suppressed throwables at the primary throwable.它还有另一个优点:当多个操作失败时,异常不会相互影响,而是在主 throwable 上注册为抑制的 throwable。 A drawback is that resources are closed in the opposite order they were created, so we have to reverse the order of the lines:一个缺点是资源的关闭顺序与创建它们的顺序相反,因此我们必须颠倒这些行的顺序:

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");
}

This example program runs through all possible scenarios.此示例程序贯穿所有可能的场景。 I shortened the output to show only some of the examples:我缩短了 output 以仅显示一些示例:

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)

A disadvantage of using the AutoCloseable interface directly, is that it declares to potentially throw Exception and hence, forces us to catch Exception .直接使用AutoCloseable接口的一个缺点是它声明可能抛出Exception ,因此迫使我们捕获Exception If the actions don't throw checked exception or a very specific type, it's useful to create your own functional interface extending AutoCloseable (In case of IOException , there is already java.io.Closeable ).如果操作没有抛出检查异常或非常特定的类型,则创建自己的扩展AutoCloseable的功能接口很有用(在IOException的情况下,已经有java.io.Closeable )。

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);
    }
}

Since this example doesn't catch exceptions, I also removed the loop which wouldn't get executed past the second iteration anyway.由于这个例子没有捕获异常,我还删除了在第二次迭代之后不会执行的循环。

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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM