[英]Checked exception is not thrown and turned into RuntimeException
這是怎么回事
為什么IOException(RemoteException)的已檢查子級被轉換為RuntimeException?
從這里摘錄的片段
import java.rmi.RemoteException;
class Thrower {
public static void spit(final Throwable exception) {
class EvilThrower<T extends Throwable> {
@SuppressWarnings("unchecked")
private void sneakyThrow(Throwable exception) throws T {
throw (T) exception; // something interesting
}
}
new EvilThrower<RuntimeException>().sneakyThrow(exception);
}
}
public class ThrowerSample {
public static void main( String[] args ) {
Thrower.spit(new RemoteException("go unchecked!"));
}
}
這是怎么回事
這段代碼規避了異常的編譯時檢查 。
使用使用已檢查異常的api並不總是很方便。
JDBC是最著名的例子之一。 使用jdbc總是需要開發人員處理SQLException
。 但是通常您不知道應該如何處理該異常。
或者,如果您使用的庫是開發人員決定從Exception
而不是RuntimeException
繼承其異常的庫。
IOException
( RemoteException
)的已檢查子級被轉換為RuntimeException
? 它不會轉換為RuntimeException
。
拋出的異常是RemoteException
:
Exception in thread "main" java.rmi.RemoteException: go unchecked!
該代碼段使用Java泛型“技巧”。 如果沒有@SuppressWarnings("unchecked")
行,編譯器將生成未經檢查的強制轉換警告。
該代碼段是Java Puzzlers的Puzzle 43的解決方案之一:陷阱,陷阱和極端案例 :
// Don’t do this - circumvents exception checking!
public static void sneakyThrow(Throwable t) {
Thread.currentThread().stop(t); // Deprecated!!
}
無需使用任何不推薦使用的方法,就可以編寫一種功能與
sneakyThrow
等效的方法。 實際上,至少有兩種方法可以做到這一點。 其中之一僅在5.0版及更高版本中有效。 你可以寫這樣的方法嗎? 它必須用Java而不是JVM字節碼編寫。 客戶端編譯后,不得更改該方法。 您的方法不一定是完美的:如果它不能拋出Exception
一個或兩個子類,則可以接受。
書中使用泛型的解決方案:
// Don’t do this either - circumvents exception checking!
class TigerThrower<T extends Throwable> {
public static void sneakyThrow(Throwable t) {
new TigerThrower<Error>().sneakyThrow2(t);
}
private void sneakyThrow2(Throwable t) throws T {
throw (T) t;
}
}
請注意這本書中的解決方案:
警告是編譯器告訴您您可能正在射擊自己的腳,實際上是這樣。 未經檢查的強制轉換警告告訴您在運行時不會檢查有問題的轉換。 當您收到未經檢查的強制轉換警告時,請修改程序以消除它,或者說服自己強制轉換不會失敗
總之,虛擬機不會強制執行Java的異常檢查。 它是一種編譯時工具,旨在簡化編寫正確程序的過程,但可以在運行時規避。 為了減少曝光,請不要忽略編譯器警告。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.