【问题标题】:execute remaining code in try block in case of exception在异常情况下执行 try 块中的剩余代码
【发布时间】:2020-09-05 10:39:43
【问题描述】:

我有以下代码:

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 块。

【问题讨论】:

  • @Holger,是的,如果第3行发生异常,应该执行第4行

标签: java exception try-catch


【解决方案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;
}

【讨论】:

    【解决方案2】:

    try with resource 语句允许指定即使在例外情况下也应执行的操作,语法简洁(与嵌套的finally 块相比)。它还有另一个优点:当多个操作失败时,异常不会相互影响,而是在主 throwable 上注册为 suppressed throwables。一个缺点是资源的关闭顺序与它们创建时的顺序相反,因此我们必须颠倒这些行的顺序:

    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)。

    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)
    

    【讨论】:

      猜你喜欢
      • 2014-07-15
      • 2014-04-12
      • 2023-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 1970-01-01
      相关资源
      最近更新 更多