在以前的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
。但如果我不这样做,上面的代码仍然编译和工作。我错过了什么吗?
参考文献:
Project Coin: multi-catch and final rethrow
Add more flexible checking for rethrown exceptions
答案 0 :(得分:24)
我相信我看到Josh Bloch发来的一条推文说,“最终”限制已经被提升了。我会看看我是否能找到一篇关于它的帖子,但我怀疑你所阅读的任何“早期”文档现在都是不准确的。
编辑:我找不到确切的“已更改”帖子,但Java 7 documentation states显示了一个示例,其中不是是最终的。当catch块声明多个类型时,它会讨论异常变量隐式 final,但这稍微是分开的。
编辑:我现在已经找到了我的困惑的来源,但它是一个内部邮件列表帖子:(无论如何,它不必被声明为final,但我相信编译器将其视为隐式 final - 就像在多捕获场景中一样。答案 1 :(得分:4)
两个编译的原因是,未随后修改的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
}
}
答案 2 :(得分:0)
没有最终它仍然是有效的java。你只是失去了“精确”的好处。