在捕获exception时是否有理由不使用final关键字?

我在一些示例BlackBerry Java类中看到了一些代码:

try { // stuff that will throw an exception } catch(final Exception e) { // deal with it } 

我认为final是为了表现。 根据标题,因为很少(永远?)任何理由修改已被抛出的exception,它们是否总是final

如果是这样,这不是编译器可以完成的事情吗? 或者由编译器完成并手动添加final没有任何影响?

Java语言规范11.2.2对最终和非最终exception进行了区分:

throw语句(第14.18节),其抛出的表达式具有静态类型E并且不是最终或有效的最终exception参数,可以抛出E或抛出的表达式可以抛出的任何exception类。
[…]
抛出语句表达式是catch子句C的最终或有效最终exception参数的throw语句可以抛出exception类E iff:

  • E是一个exception类,声明C的try语句的try块可以抛出; 和
  • E的赋值与C的任何可捕获exception类兼容; 和
  • E与同一try语句中在C左侧声明的catch子句的任何可捕获exception类不兼容。

有趣的是, JLS 14.20还说:

在uni-catch子句中,未声明为final(隐式或显式)的exception参数如果在其作用域中从不作为赋值运算符的左侧操作数发生,则被认为是有效的。

换句话说,如果你不重新分配你的catch语句的e (比如e = new SomeOtherException(); ),它将被隐式声明为final。

所以我只能得出结论,它没有什么区别,除非在catch块中修改了exception,我能想出的唯一例子是:

 public void method1() throws IOException { try { throw new IOException(); } catch (Exception e) { // e is not modified in catch => implicitly final throw e; //compiles OK } } //it works because method1 is semantically equivalent to method2: public void method2() throws IOException { try { throw new IOException(); } catch (final Exception e) { throw e; } } public void method3() throws IOException { try { throw new IOException("1"); } catch (Exception e) { e = new IOException("2"); //e modified: not implicitly final any more throw e; //does not compile } } 

我相信final在使用它的代码太长而无法轻松阅读和理解时非常有用。 例如,我会尽可能将字段设为final ,以确保它们在构造函数中正确分配,而不是在类中的任何位置进行修改。

使用final作为catch子句不太可能有用,因为a)保证设置值b)使用它的代码应该很短,c)无论如何很难修改它。

然而,没有什么能阻止你做这件事。

我不确定它是关于性能的,而是更多关于约定的。 如果您正在使用Eclipse,请尝试设置一个格式化程序,在任何可能的位置添加final关键字,并使用该格式化程序重新格式化源代码。

我已经看过几个项目,其中未修改的所有内容必须是最终的(例如参数,字段,本地变量等)。

在PMD代码分析器中还有一个相应的样式检查,它validation所有可能的内容都被声明为final

我怀疑final会真正给出任何性能优势,因为exception实例是块本地(这是一个非常好的答案,解释它https://stackoverflow.com/a/306966/492561 )。

所以它只是作为一个明确的标记,表示我不会修改。

有时您可能需要修改exception以将其丢回,可能会编辑消息以使其在更高级别更清晰。

基本上我会说这是一个偏好的问题,有些人可能会喜欢其他人可能没有。