在捕获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以将其丢回,可能会编辑消息以使其在更高级别更清晰。
基本上我会说这是一个偏好的问题,有些人可能会喜欢其他人可能没有。
- 如何在java中重启线程?
- Java Jackson:反序列化复杂的多态对象模型:JsonMappingException:意外的令牌(START_OBJECT),预期的VALUE_STRING
- 具有exception的覆盖方法
- 重写方法不会抛出exception
- 为什么我的applet得到java.security.AccessControlException:访问被拒绝(java.net.SocketPermission …),我该如何避免它?
- 为什么直接将Arrays.asList()分配给var时会出现AssertionError?
- Java,Parse JSON我知道的对象是null
- 当JMS Prod位于帮助程序POJO类中时,如何在事务中包含JMS生产者
- 为什么EOFException主要由数据输入流使用?