2010-01-03 396 views
1

我想会抛出异常的任何Throwable的包括子类的方法。我有一些需要异常的东西,将它存储在本地线程中,然后调用一个class.newInstance。该类ctor声明它抛出异常,然后接受threadlocal并抛出它。问题是,它不适合由Class.newInstance()IllegalAccessExceptionInstantiationException抛出这两个声明的异常工作。魔术异常抛出抛出异常

即时通讯使用一些sun.*类猜测任何其他方法只是一个黑客并没有真正可靠的。

包装是不是一种选择,因为这意味着捕捉器捕捉一个diff类型,这只是太简单枯燥......

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(); 
    } 
} 
+2

我不能让你尝试acheive什么.. – Bozho 2010-01-03 10:49:38

+0

我无法想象,为什么这可能是有用的。 – duffymo 2010-01-03 12:34:31

+0

我认为这只是为了好玩。你怎么能抛出一个检查的异常,而不用在throws子句中声明它呢? – 2010-01-03 13:10:26

回答

3

从Java谜题(谜题43):

public static void impossibleThrow(Throwable t) 
{ 
    Thread.currentThread().stop(t); // Deprecated method. 
} 

书显示实现了同样的问题的其他方法,一个是你的一个简化版本,其他的攻击泛型类型擦除扔任何Throwable在预期的错误。

+0

将检查出它听起来像赢家,包装太简单了,并不是完全相同的结果。 – 2010-01-03 21:33:54

3

如果你想要一个异常冒泡通过代码没想到那个异常则只是包装在一个RuntimeException

} catch (RuntimeException e) { 
    throw e; // only wrap if needed 
} catch (Exception e) { 
    throw new RuntimeException("FOO went wrong", e); 
} 

记得让消息翔实。有一天,您将不得不根据堆栈跟踪中的信息修复一个错误。

3

结束语一个RuntimeException内的异常(由托尔比约恩的建议)是要走的路。但是,您通常需要维护原始激励的堆栈跟踪。具体方法如下:

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; 
    } 
0

我修补了javac以删除错误,编译为impossibleThrow(),将源文件重命名为不以.java结尾的内容(这迫使下一次编译使用现有的.class)并使用它。

0

没有为这个问题的调试工具一定的正确性。假设你正在处理一些可能失败的代码,你会发现它(可能)会捕获某些异常并(可能)抛出某些异常。您怀疑意外的异常未被捕获。但是,底层的代码/系统太复杂,并且这个错误太时断时续了,无法让您在调试器中一步一步完成。以任何其他方式添加抛出异常而不改变方法可能是有用的。在这种情况下,使用RuntimeException封装异常将不起作用,因为您希望调用方法正常工作。