Java 7 - 精确重放,最后一个例外

2022-09-02 01:27:38

在以前版本的 java 中,重新引发异常被视为引发 catch 参数的类型。

例如:

public static void test() throws Exception{
    DateFormat df = new SimpleDateFormat("yyyyMMdd");
    try {
        df.parse("x20110731");
        new FileReader("file.txt").read();
    } catch (Exception e) {
        System.out.println("Caught exception: " + e.getMessage());
        throw e;
    }
}

在 Java 7 中,如果您声明异常,则可以更精确地了解所引发的异常:final

//(doesn't compile in Java<7)
public static void test2() throws ParseException, IOException{
    DateFormat df = new SimpleDateFormat("yyyyMMdd");
    try {
        df.parse("x20110731");
        new FileReader("file.txt").read();
    } catch (final Exception e) {
        System.out.println("Caught exception: " + e.getMessage());
        throw e;
    }
}

我的问题:文档说我需要声明例外。但是如果我不这样做,上面的代码仍然可以编译和工作。我错过了什么吗?final

引用:

项目硬币:多捕获和最终重新抛出
添加更灵活的检查以重新抛出的异常


答案 1

我相信我看到乔希·布洛赫(Josh Bloch)的一条推文说,“最终”限制已经取消了。我会看看我是否能找到一篇关于它的帖子,但我怀疑这只是你阅读的任何“早期”文档现在都不准确。

编辑:我找不到确切的“它已更改”帖子,但Java 7文档状态显示了一个示例,它不是最终的。它谈到当 catch 块声明多个类型时,异常变量是隐式最终的,但这稍微分开了。

编辑:我现在已经找到了我困惑的根源,但这是一个内部邮件列表帖子:(无论如何,它不必声明为 final,但我相信编译器将其视为隐式 final - 就像在多重捕获场景中一样。


答案 2

两者都编译的原因是,未随后修改的 uni catch 子句中的异常是隐式最终的(JLS 14.20)。

因此,对于不编译的示例,您需要以某种方式修改e,例如:

public static void test2() throws ParseException, IOException {
    DateFormat df = new SimpleDateFormat("yyyyMMdd");
    try {
        df.parse("x20110731");
        new FileReader("file.txt").read();
    } catch (Exception e) {
        if (e instanceof ParseException) {
            e = new ParseException("Better message", 0);
        } else {
            e = new IOException("Better message");
        }
        System.out.println("Caught exception: " + e.getMessage());
        throw e; //does not compile any more
    }
}