【问题标题】:Rethrowing RuntimeException as Exception将 RuntimeException 重新抛出为异常
【发布时间】:2021-10-08 14:34:28
【问题描述】:

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

【问题讨论】:

  • 是的,但您在 catch 块中不再有此信息。所以大家都知道我正在抛出一个Exception
  • JLS 的第 14.18 节似乎相关。当表达式的类型是未经检查的异常类(§11.1.1)时,在编译时抛出很好......它没有直接说明它是指声明的类型还是一些推断的运行时类型,不过,……
  • 您的代码在 Java 7 上编译和运行。
  • 虽然它不能用 Java 6 编译。我已经更新了这个问题。

标签: java exception try-catch runtimeexception


【解决方案1】:

看起来这是 Java 7 中增强的效果之一:Catching Multiple Exception Types and Rethrowing Exceptions with Improved 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 块中的另一个值,则禁用此分析。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-14
    • 2011-10-10
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多