繁体   English   中英

在方法中抛出未抛出声明的检查异常

[英]Thrown checked exception without throws declaration in method

以下代码在 Java 13 上编译运行:

public class CheckedExceptionSSCE {
    
    public static void main(String[] args) {
        try {
            methodNoThrowsDeclaration();
        } catch (Exception e) {
            // why is this throw allowed?
            // no throws in main()
            throw e;
        }
    }

    private static void methodNoThrowsDeclaration() {
        System.out.println("doesn't throw");
    }
}

为什么允许throw e

它是否在 JLS 中的某处指定? 我找不到它,也许我使用了错误的关键字进行搜索。

编译器是否足够聪明,可以推断不会抛出真正的检查异常,从而允许代码编译和运行?

这是在 Java 7 中添加的功能。如果您使用来自 catch 子句的变量重新引发异常,编译器可以派生异常类型。 由于您没有要捕获的已检查异常,因此它知道 e 只能是 RuntimeException 并且不需要 throws 定义。

更多信息: https://docs.oracle.com/javase/7/docs/technotes/guides/language/catch-multiple.html

方法:

private static void methodNoThrowsDeclaration() {
        System.out.println("doesn't throw");
    }

不抛出任何checked exception ,从这个SO 线程可以读取:

如果您真的想要,您可以抛出未经检查的异常而无需声明它们。 未经检查的异常会扩展 RuntimeException。

因此无需调整main方法签名。

Java语言规范(第 14.18 节抛出语句)可以阅读:

ThrowStatement:抛出表达式;

至少以下三个条件之一必须为真,否则会发生编译时错误:

  1. 表达式的类型是未经检查的异常 class (§11.1.1) 或 null 类型 (§4.1)。

  2. throw 语句包含在 try 语句的 try 块中(第 14.20 节),并且 try 语句不能抛出 Expression 类型的异常。 (在这种情况下,我们说抛出的值被 try 语句捕获。)

  3. throw 语句包含在方法或构造函数声明中,并且 Expression 的类型可分配(第 5.2 节)给声明的 throws 子句(第 8.4.6 节、第 8.8.5 节)中列出的至少一种类型。

您显示的代码至少遵循第一个条件。 但是,让我们看看下面的例子,其中上述三个条件都不为true ,即如果你这样做:

private static void methodNoThrowsDeclaration() {
    System.out.println("doesn't throw");
    throw new Exception();
}

这将迫使你这样做:

private static void methodNoThrowsDeclaration() throws Exception {
    System.out.println("doesn't throw");
    throw new Exception();
}

这反过来会产生编译器错误:

Unhandled exception: java.lang.Exception

在语句处throw e; .

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM