2017-07-24 84 views
1

我知道泛型類型不能擴展Throwable,我知道這是沒有意義的,因爲類型擦除(只在運行時拋出異常)和其他微妙的東西。Java - 爲什麼不能在catch子句中輸入參數?

但是Java允許類型參數被Throwable的界定其實下面的代碼是合法的

class MyClass<T extends Throwable> { /*body of the class */ } 

什麼是非法在catch子句

try { //do something that throws exception // } 
catch(T e) /* ILLEGAL!!! DOESN'T COMPILE */ {} 

使用T參數我可以理解這個約束的唯一原因是,類型參數,因爲擦除,被它的邊界類型取代,在這種情況下,這個例子是Throwable。 但類型參數也可以由一個以上的邊界類型由Object爲界,所以我可以有這種情況

class MyClass<T extends Object & Throwable> [*] 

在這種情況下T擦除之後被替換,我知道一個Object(即Throwable類型的不)變量不能在catch子句中。

讓我知道這是否是這個Java約束的原因。謝謝。

編輯: 由於davidxxx讓我注意到,這個類聲明不編譯,因爲Throwable不是一個接口。

+1

'class MyClass '不會編譯。您只能在第一種類型後指定接口。所以它應該是'MyClass '。但即使如此,你也會對'catch'語句有相同的編譯器限制。 – davidxxx

+0

你說得對。 Throwable不是一個接口。 「 - 」後綴誤導了我。 – Vin

回答

6

運行時無法檢查捕獲異常的類型是否匹配T,因爲它不知道T是什麼。

有關其他信息,請參見this question - 類型參數保留在方法和類上,但不包含變量。

catch塊的意義在於,您可以通過向異常類型提供特定的行爲來處理異常。這也是爲什麼您可以爲一個try提供多個catch區塊。沒有特定的異常類型,將無法執行正確的catch塊。

另外,如果您使用原始類型運行代碼,您希望代碼執行什麼操作?你建議的方式,T將被替換爲Throwablecatch塊現在會捕獲所有異常,而不是隻有某些類型的異常。

另外,JLS指定CatchType爲:

CatchType: 
    ClassType 
    ClassType | CatchType 

其不包括TypeArgument

如果你真的要做到這一點,你可以捕捉Throwable和使用instanceof或使用其Class檢查類型:

try { 
    doSomethingDangerous(); 
} catch (Throwable t) { 
    if (t instanceof IOException) { 
     handleIoException(t); 
    } else if (...) { 
     ... 
    } else { 
     handleOther(t); 
    } 
} 

注:Catching Throwable or Exception is usually considered very bad practice

編輯:here's what it looks like in C# for possible reference

+0

因此,如果我有'MyClass c = ...',並且'catch'子句中'T'是合法的,則在運行時'catch {}'塊也會處理不同類型的異常,例如'NullPointerException ''或'Exception'等。是不是? – Vin

+0

@Vin理論上,一個NPE _將被處理(但是'Exception'不會因爲'RuntimeException'實際上是'Exception'的一個子類。)例如,[可以在C#中執行此操作](http:///ideone.com/N9tXAs)如果你想要一個它的樣子的例子。 – Moira

+0

好的。我不明白'RuntimeException'是'Exception'的一個子類。用'Throwable'代替'T',不管實際的類型參數是什麼,捕獲塊處理每種類型的'Throwable'。從理論上講, – Vin

相關問題