[英]Why do I have to deal with Throwable if I invoke getCause() on an Exception
它是用Java設計的,如果我在Exception
上調用getCause()
,則會得到Throwable
對象。
我知道getCause()
只是從Throwable
繼承的,我知道Throwable
可以是Error
或Exception
,但是程序員通常只應在Exception
級別上工作,而不處理Throwable
/ Error
類。
例如,在Java異常層次結構設計中是什么原因導致在Exception
類中不包含getCause()
會返回Exception
對象?
這是從Java Concurrency in Practice (Brian Goetz)中摘錄的不便之處:
public class Preloader {
private final FutureTask<ProductInfo> future =
new FutureTask<ProductInfo>(new Callable<ProductInfo>() {
public ProductInfo call() throws DataLoadException {
return loadProductInfo();
}
});
private final Thread thread = new Thread(future);
public void start() { thread.start(); }
public ProductInfo get()
throws DataLoadException, InterruptedException {
try {
return future.get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause instanceof DataLoadException)
throw (DataLoadException) cause;
else
throw launderThrowable(cause);
}
}
}
書中說:
...還因為
ExecutionException
的原因作為Throwable
返回,因此不方便處理...
在launderThrowable()
它立即處理Error
(因為我們不想處理它)並返回RuntimeException
:
public static RuntimeException launderThrowable(Throwable t) {
if (t instanceof RuntimeException)
return (RuntimeException) t;
else if (t instanceof Error)
throw (Error) t;
else
throw new IllegalStateException("Not unchecked", t);
}
getCause
是在Throwable
定義的Throwable
,並在Exception
簡單地繼承 。 Throwable
的原因僅僅是Throwable
(可能是Exception
或Error
)。
IMO有一個說getCauseAsException
的方法,如果有任何原因,它僅會返回一個Exception
,因為cause異常並不是真正有用的。 如果您只關心Exception
而不是Error
則可以簡單地調用getCause()
並檢查它是否是Exception
的實例。
首先,如果您的類型具有幾個子類型,並且它們的行為確實相同,那么在父類中定義方法是有意義的。 基本上,設計師們說的是:“ Throwable
可以有一個原因,這也是一個拋出,你可以得到的原因”。 而且您可以在Exception
和Error
中都這樣做,因為它們都碰巧是可拋出的。
現在, Throwable
層次結構從Java 1.0開始就存在,並且泛型在那里不存在。 如今,您可能已經可以定義如下行為:
class ModernThrowable<T extends ModernThrowable<T>> {
T getCause() {...}
}
然后,您可以將ModernException
定義為extends ModernThrowable<ModernException>
,然后您可以得到所需的行為。
但是這種設計當時還不存在,因此您獲得了Throwable
支持,因此必須進行轉換。 這就是過去的工作方式,您必須保持向后兼容性。
但是實際上……聽起來可能如此 , 這是不正確的 。 至少,這不是全部。
得到Error
作為Exception
的原因是完全可以的。 看一看javax.management.RuntimeErrorException
。 當您使用代理程序時,您可能會收到Error
,在這些特殊情況下,該Error
不應導致您立即中止系統。 因此,您將其作為此特殊Exception的原因。 因此,您的getCause()
實際上會從Exception
返回一個Error
。
因此,如果它不是這樣設計的,那么您就必須經過一番考驗-專門針對這種特殊異常的原因使用一種特殊方法。
程序員在實現應用程序時通常在異常級別工作。 但是請記住,例如,JVM也是用Java實現的,在這種情況下,程序員也應該在Throwable / Error級別上工作。
因此,在異常層次結構樹的哪個級別上應該解決的問題更多是要實現的系統域問題,而不是語言設計本身問題。 因此從語言設計的角度來看,最好在Throwable類中提供getCause方法,該類是層次結構樹的根。 由於Exception類從其父類繼承了此方法,因此不必僅在某些特定域中就不/不應使用Throwable實例來提供具有不同返回類型的相同方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.