首页 > 解决方案 > 将 RuntimeException 重新抛出为异常

问题描述

Java 允许我毫无问题地编译以下代码:

public class Test {
    public static void main(String[] args){
        try {
            throw new RuntimeException();
        } catch (Exception e) {
            throw e;
        }
    }
}

即使java.lang.Exception是一个检查异常。这意味着我将重新抛出未经检查的异常作为已检查并侥幸逃脱。

Java 编译器很可能能够确定在 try 块中没有引发检查异常,但我在规范中找不到支持该异常的部分。

可以依赖这种行为并从哪个 JDK 版本开始吗?

更新:此类无法使用 Java 1.6.0_38 编译,并显示以下消息:

Test.java:6: unreported exception java.lang.Exception; must be caught or declared to be thrown
            throw e;
            ^
1 error

标签: javaexceptiontry-catchruntimeexception

解决方案


看起来这是 Java 7 中增强的效果之一:Catching Multiple Exception Types and Rethrowing Exceptions with Improvement Type Checking。请参阅“使用更具包容性的类型检查重新引发异常”部分。

Java SE 7 编译器可以确定语句 throw e 抛出的异常一定来自 try 块,而 try 块抛出的异常只能是 FirstException 和 SecondException。即使 catch 子句的异常参数 e 是 Exception 类型,编译器也可以确定它是 FirstException 或 SecondException 的实例。

请注意,即使在 Java 7 及更高版本中,以下内容也不会编译:

public class Test {
    public static void main(String[] args){
        try {
            throw new RuntimeException();
        } catch (Exception e) {
            Exception e1 = e;
            throw e1;
        }
    }
}

因为:

如果将 catch 参数分配给 catch 块中的另一个值,则禁用此分析。


推荐阅读