2010-01-03 324 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封裝異常將不起作用,因爲您希望調用方法正常工作。