执行try块中剩余的代码,以处理异常情况。

huangapple go评论83阅读模式
英文:

execute remaining code in try block in case of exception

问题

我有如下的代码:

try{
  line1; // 可能会抛出异常
  line2; // 可能会抛出异常
  line3; // 可能会抛出异常
  line4; // 可能会抛出异常
}catch(Exception e){
   处理异常;
}finally{
  完成剩余工作;
}

我需要在发生上述行中的异常时执行 try 块内的所有 4 行代码。假设代码在 try 块的第 2 行遇到异常,即使这样,我仍然需要执行第 3 行和第 4 行代码(这两行也可能会抛出异常)。除了使用多个 try-catch 块外,是否有更简单的方法来实现这一点?

英文:

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.

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). Is there an easy way to do this instead of having multiple try-catch blocks.

答案1

得分: 1

你可以在外部的 try/catch 块内部使用 try/catch 块,如果有意义的话。类似这样:

try {
  line1; // 可能会抛出异常
  try {
    line2; // 可能会抛出异常
  } catch (Exception e) {
    if (e 是一个很严重的异常) throw e;  // 不继续执行
    else System.out.println("line2 失败,但我会继续进行");
  }
  try {
    line3; // 可能会抛出异常
  } catch (Exception e) {
    if (e 是一个很严重的异常) throw e;  // 不继续执行
    else System.out.println("line3 失败,但我会继续进行");
  }
  line4; // 可能会抛出异常
} catch (Exception e) {
  处理异常;
} finally {
  完成剩余操作;
}
英文:

You can have try/catch blocks within the outer try/catch block if it makes sense to. 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;
}

答案2

得分: 1

try with resource 语句允许指定即使在异常情况下也应执行的操作,具有简洁的语法(与嵌套的 finally 块相比)。它还有另一个优点:当多个操作失败时,异常不会相互遮盖,而是在主异常中注册为[被抑制的]可抛出项。缺点是资源的关闭顺序与它们创建的顺序相反,因此我们必须反转行的顺序:

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

// ... (以下的 line2、line3 和 line4 方法类似)

这个示例程序运行了所有可能的情景。我缩短了输出,只展示了部分示例:

```plaintext`

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)

// ... (其他测试的输出)


使用 `AutoCloseable` 接口的一个缺点是,它声明可能会抛出 `Exception`,因此强制我们捕获 `Exception`。如果这些操作不会抛出已检查的异常或非常特定的类型,可以创建自己的扩展 `AutoCloseable` 的功能性接口(在 `IOException` 的情况下,已经有了 `java.io.Closeable` 接口)。

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

由于这个示例不捕获异常,我还删除了循环,因为循环在第二次迭代后不会被执行。

英文:

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). 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. 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 &lt; 16; test++) {
        int currentTest = test;
        System.out.println(&quot;Test &quot;+currentTest);

        try(AutoCloseable c1 = () -&gt; line4(currentTest);   // 4
            AutoCloseable c2 = () -&gt; line3(currentTest);   // 3
            AutoCloseable c3 = () -&gt; line2(currentTest)) { // 2
            line1(currentTest);                            // 1
        }
        catch(Exception ex) {
            System.out.print(&quot;got exception &quot;);
            ex.printStackTrace(System.out);
        }

        System.out.println();
    }
}
public static void line1(int whichTest) {
    if((whichTest &amp; 1) != 0) {
        System.out.println(&quot;letting line 1 fail&quot;);
        throw new RuntimeException(&quot;line 1 failed&quot;);
    } else System.out.println(&quot;line1 executed&quot;);
}
public static void line2(int whichTest) {
    if((whichTest &amp; 2) != 0) {
        System.out.println(&quot;letting line 2 fail&quot;);
        throw new RuntimeException(&quot;line 2 failed&quot;);
    } else System.out.println(&quot;line2 executed&quot;);
}
public static void line3(int whichTest) {
    if((whichTest &amp; 4) != 0) {
        System.out.println(&quot;letting line 3 fail&quot;);
        throw new RuntimeException(&quot;line 3 failed&quot;);
    } else System.out.println(&quot;line3 executed&quot;);
}
public static void line4(int whichTest) {
    if((whichTest &amp; 8) != 0) {
        System.out.println(&quot;letting line 4 fail&quot;);
        throw new RuntimeException(&quot;line 4 failed&quot;);
    } else System.out.println(&quot;line4 executed&quot;);
}

This example program runs through all possible scenarios. I shortened the output to show only some of the examples:

<!-- language: lang-none -->

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)

<!-- language: lang-none -->

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)

<!-- language: lang-none -->

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

interface MyAction extends AutoCloseable {
    @Override public void close();
}    
public static void main(String[] args) {
    int currentTest = 11;

    try(MyAction c1 = () -&gt; line4(currentTest);
        MyAction c2 = () -&gt; line3(currentTest);
        MyAction c3 = () -&gt; 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.

<!-- language: lang-none -->

letting line 1 fail
letting line 2 fail
line3 executed
letting line 4 fail
Exception in thread &quot;main&quot; 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)

huangapple
  • 本文由 发表于 2020年5月19日 19:21:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/61889799.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定