首页 > 解决方案 > 在java中抛出通用异常

问题描述

我有另一个来自 javaDeathMatch 游戏的具有挑战性的问题;在下面的代码中,我们被问到下面的代码有什么样的问题。如果我错了,请纠正我;编译错误:无;在编译时,类型参数的擦除还没有发生,动态绑定还没有发生,所以传递给 SQLException 类型的方法的参数在方法“pleaseThrow”中被认为是异常,它(我的意思是Exception not SQLException) 在方法中被强制转换为运行时异常,没有错误。唯一的错误是我们没有适当的 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") 永远不会被打印!!!问题是什么????

标签: javagenericsexceptionpolymorphismtry-catch

解决方案


这是由于类型擦除。在编译后的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 块永远不会到达。你试图捕捉RuntimeExceptions,但你实际上抛出的是一个检查异常。然后向上传播并最终被 JVM 捕获。

补充阅读:Oracle 类型擦除教程


推荐阅读