该实用工具类重新抛出一个Throwable作为选中?(Utility class that re-t

2019-07-04 02:05发布

我捕捉在单元测试包装方法的所有可抛出,以便在外部系统重置一些数据。 我想重新抛出原始异常时这样做,我使用这段代码做到这一点:

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

然而,没有任何现有的工具调用已经做了这个?

(因为AssertionErrors是错误,我赶上抛出异常。)

编辑:说实话,我真的不希望来包装异常,所以任何伎俩,让我扔任何抛出(包括托运例外)没有声明抛出是可以接受的。

Answer 1:

是的,有写的,这将避免包装你的checked异常的方法的一种方式。 对于这种使用情况下,它是一个完美的比赛,但你一定要非常小心了,因为它可以很容易混淆的门外汉。 这里是:

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

你会使用它作为

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

正如评论说约阿希姆·绍尔,在某些情况下,它可以帮助说服调用行的编译器sneakyThrow导致方法来终止。 我们可以只改变声明的返回类型:

@SuppressWarnings("unchecked")
public static <T extends Throwable> void 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指令。 该方法甚至合法声明抛出任何Throwable ,这是擦除T



Answer 2:

伟大的番石榴库有一个方法Throwables.propagate(Throwable)那不正是你的代码是这样做的: 的JavaDoc

从文档:

传播Throwable作为-是,如果它是RuntimeException或Error的一个实例,或者作为最后的手段,将其包装在一个RuntimeException然后传播。



Answer 3:

也许setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler)可以帮助你。 在那里,你可以定义一个全局异常处理程序中发生的所有异常。



文章来源: Utility class that re-throws a throwable as unchecked?