我想要一个可以抛出任何Throwable的方法,包括Exception的子类。我得到了一个异常的东西,将它藏在本地的一个线程中,然后调用一个class.newInstance。该类ctor声明它抛出Exception然后获取threadlocal并抛出它。问题是它不适用于Class.newInstance()
引发的两个声明的异常,即IllegalAccessException
和InstantiationException
。
我猜测使用某些sun.*
类的任何其他方法只是一个黑客而且不太可靠。
包装不是一种选择,因为这意味着捕手正在捕捉差异类型,这太简单而且无聊......
static public void impossibleThrow(final Throwable throwable) {
Null.not(throwable, "throwable");
if (throwable instanceof RuntimeException) {
throw (RuntimeException) throwable;
}
if (throwable instanceof Error) {
throw (Error) throwable;
}
try {
THROW.set((Exception) throwable);
THROWER.newInstance();
} catch (final InstantiationException screwed) {
throw new Error(screwed);
} catch (final IllegalAccessException screwed) {
throw new Error(screwed);
} finally {
THROW.remove();
}
}
private final static Class<Impossible> THROWER = Impossible.class;
private final static ThreadLocal<Exception> THROW = new ThreadLocal<Exception>();
static private class Impossible {
@SuppressWarnings("unused")
public Impossible() throws Exception {
throw THROW.get();
}
}
答案 0 :(得分:3)
如果你想要一个Exception通过不期望该异常的代码冒泡,那么只需将它包装在RuntimeException中
} catch (RuntimeException e) {
throw e; // only wrap if needed
} catch (Exception e) {
throw new RuntimeException("FOO went wrong", e);
}
请记住让信息提供信息。有一天,您将不得不仅根据堆栈跟踪中的信息修复错误。
答案 1 :(得分:3)
在RuntimeException中包装异常(如Thorbjørn所建议)是要走的路。但是,您通常希望保持原始excpetion的堆栈跟踪。方法如下:
public static void rethrow(final Throwable t)
{
if(t instanceof RuntimeException)
throw (RuntimeException) t;
RuntimeException e = new RuntimeException(t);
e.setStackTrace(t.getStackTrace());
throw e;
}
答案 2 :(得分:3)
来自Java Puzzlers(谜题43):
public static void impossibleThrow(Throwable t)
{
Thread.currentThread().stop(t); // Deprecated method.
}
这本书展示了实现同样问题的其他方法,一个是你的简化版本,另一个利用泛型类型擦除来抛出任何Throwable,预计会出现错误。
答案 3 :(得分:0)
我修补了javac以删除错误,编译了impossibleThrow(),将源文件重命名为不以.java结尾的东西(强制下一次编译使用现有的.class)并使用它。
答案 4 :(得分:0)
这个问题作为调试工具有一定的效力。假设您正在处理可能失败的一些代码,并且您发现它(可能)捕获某些异常并且(可能)抛出某些异常。您怀疑未捕获到意外的异常。但是,底层代码/系统太复杂,并且错误太间歇,无法让您在调试器中单步执行。添加抛出异常而不以任何其他方式更改方法可能很有用。在这种情况下,使用RuntimeException包装异常将不起作用,因为您希望调用方法正常运行。