我有另一个来自 javaDeathMatch 游戏的具有挑战性的问题; 在下面的代码中,我们被询问下面的代码有什么样的问题。 如果我错了,请纠正我; 编译错误:无;在编译时,类型参数的删除还没有发生,动态绑定(bind)也没有发生,所以传递给 SQLException 类型方法的参数被认为是方法“pleaseThrow”中的异常,它(我的意思是Exception not SQLException) 在方法中被转换为 Runtime Exception 而没有错误。唯一的错误是我们没有合适的 catch 子句来捕获异常。
public class Exption<T extends Exception> {
public static void main(String[] args) {
try {
new Exption<RuntimeException>().pleaseThrow(new SQLException());
}catch (final SQLException ex){
ex.printStackTrace();
}
}
private void pleaseThrow(final Exception t) throws T{
throw (T)t;
}
}
如果我们用这个替换 catch 子句:
catch(final RuntimeException e){
e.printStackTrace();
System.err.println("caught");
}
异常将被捕获,但 System.err.println("caught") 永远不会被打印!!!什么问题????
最佳答案
这是由于类型删除。在编译后的 java 中,所有通用信息都会丢失(还有一些东西,但与此无关)。这意味着在编译期间,通用变量 T
等于 RuntimeException
。所以你的 pleaseThrow 代码看起来像这样:
private void pleaseThrow(final Exception t) throws RuntimeException{
throw (RuntimeException)t;
}
虽然在编译之后,每个泛型参数都被删除为基类型。在您的情况下,Exception
。这给您留下了这样的方法签名:
private void pleaseThrow(final Exception t) throws Exception{
throw (Exception)t;
}
终于清楚了,为什么您的 catch block 永远不会到达。您正试图捕获 RuntimeExceptions
但您实际抛出的是一个已检查的异常。然后向上传播并最终被 JVM 捕获。
Additional reading: Oracle Tutorial on type erasure
关于java - 在java中抛出通用异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51097975/