Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
275 views
in Technique[技术] by (71.8m points)

java - Utility class that re-throws a throwable as unchecked?

I am catching all throwables in a unit test wrapper method in order to reset some data in an external system. I want to re-throw the original exception when this is done and I am using this piece of code to do it:

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

However, is there any existing utility call that does this already?

(I am catching throwables because AssertionErrors are Errors.)

Edit: To be honest, I don't really want to wrap the exception, so any trick that would allow me to throw any throwable (including checked exceptions) without declaring throws is acceptable.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Yes, there is a way to write a method that will avoid wrapping your checked exceptions. For this use case it is a perfect match, although you should definitely be very careful with it, since it can easily confuse the uninitiated. Here it is:

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

and you'd use it as

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

As commented by Joachim Sauer, in certain cases it helps convince the compiler that the line calling sneakyThrow causes the method to terminate. We can just change the declared return type:

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

and use it like this:

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

For educational purposes it is nice to see what's going on at the bytecode level. The relevant snippet from 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;

Note there is no checkcast instruction. The method even legitimately declares to throw T, which can be any Throwable.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...