groovy 避免在finally块可能引发异常时隐藏异常

ctehm74n  于 2023-10-15  发布在  其他
关注(0)|答案(3)|浏览(113)

当你有一个进程,你已经 Package 在一个try,catch,finally中,并且final中的操作可能会抛出,你如何处理异常,隐藏?
下面是一个问题和可能的解决方案的示例。修复看起来还可以吗,还是我重新扔得很差?

隐藏问题代码

try {
  // try-block
  setupTestEnv();
  runTests();
} finally {
  // finally-block
  cleanupTestEnv();
}
  • try-block抛出仍然会导致清理并被抛出到调用堆栈中
  • try-block throw,其中finally-block throw也会导致try-block throw的丢失或隐藏,因为finally-block throw在调用堆栈中向上移动。

可能的解决方法

改编自https://stackoverflow.com/a/41246027/9950

Throwable tryBlockException;
try {
  setupTestEnv();
  runTests();
} catch (Throwable t) {
  // record and throw
  tryBlockException = t;
  throw ex;
} finally {
   try {
      cleanupTestEnv()
   } catch (Throwable t) {
      if (tryBlockException != null) {
         // we have an exception from try-block
         // and that's priority exception

         // add the cleanup exception as suppressed
         // it'll be in the object and call reporting
         tryBlockException.addSuppressed(t);
         throw tryBlockException;
      } else {
         throw t;
      }
  }
}
3qpi33ja

3qpi33ja1#

我看没问题。我建议将大部分代码放在一个可重用的方法中,例如:

public interface Attempt {
    void apply() throws Exception;
}

public static void tryCatchFinally(
        Attempt mainF,
        Attempt finallyF
) throws Exception {
    Exception tryCatchException = null;
    try {
        mainF.apply();
    } catch (Exception ex) {
        tryCatchException = ex;
        throw ex;
    } finally {
        try {
            finallyF.apply();
        } catch (Exception ex) {
            if (tryCatchException != null) {
                tryCatchException.addSuppressed(ex);
            }
        }
    }
}

你可以这样使用它:

tryCatchFinally(
        () -> {setupTestEnv(); runTests();},
        () -> cleanupTestEnv()
);
jgwigjjp

jgwigjjp2#

这是一种方法,除了在您的情况下,它不是t而是被抑制的tryblockexception,并且您也不需要重新抛出tryblockexception。
其他的选项是自动关闭类型的try-with-resources,或者在可能的情况下确保finally子句不会抛出ex,因为它可以吞下try块中的异常。

ffscu2ro

ffscu2ro3#

我不知道为什么你必须以如此复杂的方式使用finally。你也可以只使用在try-catch块之后运行的代码:

Exception priorityException;
try {
  setupTestEnv();
  runTests();
} catch (Exception ex) {
  priorityException = ex;  // delayed handling
}

try {
  cleanupTestEnv();
} catch (Exception ex) {
  if (priorityException != null) {
    priorityException.addSuppressed(ex);
  } else {
    priorityException = ex;
  }
  throw priorityException;
}

请注意,我使用了catch (Exception ...)而不是您的Throwable,因为捕获和处理Error s通常不可能以有用的方式进行。参见SO问题Catching Java errors及其答案以获得更好的见解。

相关问题