簡體   English   中英

如果在異常上調用getCause(),為什么還要處理Throwable

[英]Why do I have to deal with Throwable if I invoke getCause() on an Exception

它是用Java設計的,如果我在Exception上調用getCause() ,則會得到Throwable對象。

我知道getCause()只是從Throwable繼承的,我知道Throwable可以是ErrorException ,但是程序員通常只應在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 (可能是ExceptionError )。

IMO有一個說getCauseAsException的方法,如果有任何原因,它僅會返回一個Exception ,因為cause異常並不是真正有用的。 如果您只關心Exception而不是Error則可以簡單地調用getCause()並檢查它是否是Exception的實例。

首先,如果您的類型具有幾個子類型,並且它們的行為確實相同,那么在父類中定義方法是有意義的。 基本上,設計師們說的是:“ Throwable可以有一個原因,這也是一個拋出,你可以得到的原因”。 而且您可以在ExceptionError中都這樣做,因為它們都碰巧是可拋出的。

現在, 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM