我知道泛型类型不能扩展 Throwable,我知道这没有意义,因为类型擦除(异常仅在运行时抛出(和其他微妙的事情。
但是Java允许类型参数由Throwable限制,实际上以下代码是合法的
class MyClass<T extends Throwable> { /*body of the class */ }
在catch 子句中使用T
参数是非法
try { //do something that throws exception // }
catch(T e) /* ILLEGAL!!! DOESN'T COMPILE */ {}
我能理解这个约束的唯一原因是类型参数,因为擦除,被它的边界类型所取代,在本例中Throwable
。 但是类型参数也可以由多个边界类型限定,所以我可能会遇到这种情况
class MyClass<T extends Object & Throwable> [*]
在这种情况下,T
在擦除后被Object
替换,我知道Object
(不是Throwable
类型(变量不能在 catch 子句中。
让我知道这是否是这个 Java 约束的原因。谢谢。
编辑: [*]正如 davidxxx 让我注意到的那样,这个类声明无法编译Throwable
因为它不是一个界面。
运行时无法检查捕获的异常类型是否与T
匹配,因为它不知道T
是什么。
有关其他信息,请参阅此问题 - 类型参数保留在方法和类上,但不保留变量。
catch
块的要点是,您可以通过向异常类型提供特定行为来处理异常。这也是为什么您可以为单个try
提供多个catch
块的原因。如果没有特定的异常类型,就不可能执行正确的catch
块。
另外,如果使用原始类型运行代码,您希望代码执行什么操作?您建议的方式,T
将被替换为Throwable
,并且catch
块现在将捕获所有异常,而不仅仅是特定类型的异常。
此外,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);
}
}
注意:捕捉Throwable
或Exception
通常被认为是非常糟糕的做法。
编辑:这是它在 C# 中的外观,以供参考。