Java 7 – 精确重新抛出最终exception

在以前的java版本中,重新抛出exception被视为抛出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中,如果您声明exceptionfinal ,则可以更精确地了解抛出的exception:

 //(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; } } 

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

参考文献:

项目硬币:多次捕获和最终重新抛出
为重新抛出的exception添加更灵活的检查

相信我看到Josh Bloch发来的一条推文说,“最终”的限制已经被提升了。 我会看看我是否能找到一篇关于它的post,但我怀疑你所阅读的任何“早期”文档现在都是不准确的。

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

编辑:我现在已经找到了我的困惑的来源,但它是一个内部邮件列表post:(无论如何,它不必被宣布为最终,但我相信编译器将其视为隐式最终 – 就像在多捕捉场景。

这两个编译都是因为未在后续修改的uni catch子句中的exception是隐式最终的( 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 } } 

没有最终它仍然是有效的java。 你只是失去了“精确”的好处。