java - 将 throwable 重新抛出为未检查的实用程序类?

标签 java exception utility-method

我正在单元测试包装器方法中捕获所有可抛出的对象,以便重置外部系统中的一些数据。完成后我想重新抛出原始异常,我正在使用这段代码来完成它:

if (t instanceof RuntimeException) {
    throw (RuntimeException) t;
} else if (t instanceof Error) {
    throw (Error) t;
} else {
    throw new RuntimeException(t);
}

但是,是否有任何现有的实用程序调用已经执行此操作?

(我正在捕获 throwable,因为 AssertionErrors 是错误。)

编辑:老实说,我真的不想包装异常,所以任何允许我在不声明抛出的情况下抛出任何可抛出(包括检查的异常)的技巧都是可以接受的。

最佳答案

是的,有一种方法可以编写避免包装已检查异常的方法。对于这个用例,它是一个完美的匹配,尽管你绝对应该非常小心,因为它很容易混淆外行。在这里:

@SuppressWarnings("unchecked")
public static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
    throw (T) t;
}

你会把它当作

catch (Throwable t) { sneakyThrow(t); }

正如 Joachim Sauer 评论的那样,在某些情况下,它有助于让编译器相信调用 sneakyThrow 的行会导致方法终止。我们可以只更改声明的返回类型:

@SuppressWarnings("unchecked")
public static <T extends Throwable> T sneakyThrow(Throwable t) throws T {
    throw (T) t;
}

并像这样使用它:

catch (Throwable t) { throw sneakyThrow(t); }

出于教育目的,很高兴看到字节码级别发生了什么。 javap -verbose UncheckedThrower 中的相关片段:

public static <T extends java.lang.Throwable> java.lang.RuntimeException sneakyThrow(java.lang.Throwable) throws T;
  descriptor: (Ljava/lang/Throwable;)Ljava/lang/RuntimeException;
  flags: ACC_PUBLIC, ACC_STATIC
  Code:
    stack=1, locals=1, args_size=1
       0: aload_0
       1: athrow
  Exceptions:
    throws java.lang.Throwable
  Signature: #13                          // <T:Ljava/lang/Throwable;>(Ljava/lang/Throwable;)Ljava/lang/RuntimeException;^TT;

注意没有checkcast指令。该方法甚至合法地声明要抛出 T,它可以是任何 Throwable

关于java - 将 throwable 重新抛出为未检查的实用程序类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13528624/

相关文章:

java - Java 中未处理的异常

c# - 如果 "Utilities"类是邪恶的,我应该把我的通用代码放在哪里?

java - 使用 JPA 通过一列连接并返回另一列

Java Jsoup 迭代下拉列表并抓取动态添加的数据

java - Java 中的检查异常与非检查异常

python - 在哪里放置我想在我开发的多个包/项目中使用的小实用函数?

c# - 我应该将常用实用方法放在 Asp.Net Core MVC 项目中的哪里?

java - Libsvm 类不在 CLASSPATH 中

java - 通话时编辑语音 - Android

java - log4j:错误 "org.apache.log4j.ConsoleAppender"对象不可分配给 "org.apache.log4j.Appender"变量