Java - 为什么不能在catch子句中键入参数?

Vin*_*Vin 3 java generics try-catch

我知道泛型类型不能扩展Throwable,我知道这没有意义,因为类型擦除(异常只在运行时抛出)和其他微妙的东西.

但是,Java允许类型参数受Throwable限制,实际上以下代码是合法的

class MyClass<T extends Throwable> { /*body of the class */ }
Run Code Online (Sandbox Code Playgroud)

什么是非法的是T在catch子句中使用参数

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

我能理解这个约束的唯一原因是,在这种情况下,type参数,因为擦除,被它的边界类型所取代Throwable.但是类型参数也可能受到多个边界类型的限制,所以我可能会遇到这种情况

class MyClass<T extends Object & Throwable> [*]
Run Code Online (Sandbox Code Playgroud)

在这种情况下T,在擦除之后被替换,Object并且我知道Object(不是类型Throwable)变量不能在catch子句中.

如果这是Java约束的原因,请告诉我.谢谢.

编辑:[*]由于davidxxx让我注意到,这个类声明不编译,因为Throwable它不是一个接口.

Moi*_*ira 8

运行时无法检查捕获的异常的类型是否匹配,T因为它不知道是什么T.

有关其他信息,请参阅此问题 - 类型参数保留在方法和类中,但不保存在变量上.

A的得分catch块,你可以通过向异常类型提供特定行为处理异常.这也是catch为单个提供多个块的原因try.如果没有特定的异常类型,则无法执行正确的catch块.

此外,如果您使用原始类型运行代码,您希望代码做什么?您提出的方式T将被替换为,Throwable并且catch块现在将捕获所有异常,而不仅仅是某种类型的异常.

此外,JLS指定CatchType为:

CatchType:
    ClassType
    ClassType | CatchType
Run Code Online (Sandbox Code Playgroud)

不包括TypeArgument.

如果你真的想这样做,你可以Throwable使用instanceof或使用它来捕获并检查类型Class:

try {
    doSomethingDangerous();
} catch (Throwable t) {
    if (t instanceof IOException) {
        handleIoException(t);
    } else if (...) {
        ...
    } else {
        handleOther(t);
    }
}
Run Code Online (Sandbox Code Playgroud)

注意:捕捉ThrowableException通常被认为是非常糟糕的做法.

编辑:这是C#中的可能参考.