2017-07-24 83 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

相关问题