我知道泛型类型不能扩展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 */ {}
我能理解这个约束的唯一原因是type参数,因为擦除,被它的边界类型取代,在本例中是Throwable
。
但是类型参数也可能受到多个边界类型的限制,所以我可能会出现这种情况
class MyClass<T extends Object & Throwable> [*]
在这种情况下T
在被Object
擦除后被替换,我知道Object
(不是Throwable
类型)变量不能在catch子句中
让我知道这是否是这个Java约束的原因。感谢。
编辑:
[*]由于davidxxx让我注意到,这个类声明没有编译,因为Throwable
不是接口。
答案 0 :(得分:7)
运行时无法检查捕获的异常的类型是否与T
匹配,因为它不知道T
是什么。
有关其他信息,请参阅this question - 类型参数保留在方法和类中,但不保存在变量中。
catch
块的要点是您可以通过向异常类型提供特定行为来处理异常。这也是您可以为单个catch
提供多个try
块的原因。如果没有特定的异常类型,则无法执行正确的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);
}
}
注意:Catching Throwable
or Exception
is usually considered very bad practice。